# Calendar.social # Copyright (C) 2018 Gergely Polonkai # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . """Gregorian calendar system for Calendar.social """ from datetime import datetime, timedelta from flask_babelex import lazy_gettext as _ from . import CalendarSystem class GregorianCalendar(CalendarSystem): """Gregorian calendar system for Calendar.social """ __name__ = _('Gregorian') __has_months__ = True START_DAY = 0 END_DAY = 7 month_names = ( _('January'), _('February'), _('March'), _('April'), _('May'), _('June'), _('July'), _('August'), _('September'), _('October'), _('November'), _('December'), ) day_names = ( _('Monday'), _('Tuesday'), _('Wednesday'), _('Thursday'), _('Friday'), _('Saturday'), _('Sunday'), ) def __init__(self, timestamp): self.timestamp = datetime.utcfromtimestamp(timestamp) @property def month(self): return self.timestamp.strftime("%B, %Y") @property def days(self): day_list = [] month_first = self.timestamp.replace(day=1) if self.timestamp.month == 12: month_last = month_first.replace(day=31) else: month_last = month_first.replace(month=month_first.month + 1) - timedelta(days=1) pad_before = (7 - self.START_DAY + month_first.weekday()) % 7 pad_after = (6 - month_last.weekday() + self.START_DAY) % 7 first_display = month_first - timedelta(days=pad_before) last_display = month_last + timedelta(days=pad_after) current = first_display while current <= last_display: day_list.append(current) current += timedelta(days=1) return day_list @property def prev_year(self): """Returns the timestamp of the same date in the previous year """ return self.timestamp.replace(year=self.timestamp.year - 1) @property def prev_year_year(self): """The number of the previous year """ return self.timestamp.replace(year=self.timestamp.year - 1).year @property def prev_month(self): """Returns the timestamp of the same day in the previous month """ if self.timestamp.month == 1: return self.prev_year.replace(month=12) return self.timestamp.replace(month=self.timestamp.month - 1) @property def prev_month_name(self): """The name of the previous month """ if self.timestamp.month == 1: timestamp = self.prev_year.replace(month=12) else: timestamp = self.timestamp.replace(month=self.timestamp.month - 1) return self.month_names[timestamp.month - 1] @property def next_month(self): """Returns the timestamp of the same day in the next month """ if self.timestamp.month == 12: return self.next_year.replace(month=1) return self.timestamp.replace(month=self.timestamp.month + 1) @property def next_month_name(self): """The name of the next month """ if self.timestamp.month == 12: timestamp = self.prev_year.replace(month=1) else: timestamp = self.timestamp.replace(month=self.timestamp.month + 1) return self.month_names[timestamp.month - 1] @property def next_year(self): """Returns the timestamp of the same date in the next year """ return self.timestamp.replace(year=self.timestamp.year + 1) @property def next_year_year(self): """The number of the next year """ return self.timestamp.replace(year=self.timestamp.year + 1).year @property def has_today(self): """``True`` if the set month holds today’s date """ now = datetime.utcnow() month_start_timestamp = self.timestamp.replace(day=1, hour=0, minute=0, second=0, microsecond=0) if self.timestamp.month == 12: next_month = 1 else: next_month = self.timestamp.month + 1 month_end_timestamp = month_start_timestamp.replace(month=next_month) return month_start_timestamp <= now < month_end_timestamp @staticmethod def day_events(date, user=None): """Returns all events for a given day """ from ..models import Event, EventVisibility, Invitation, Profile, Response events = Event.query if user: events = events.outerjoin(Invitation) \ .outerjoin(Response) \ .join(Profile, Event.profile) \ .filter(Profile.user == user) start_timestamp = date.replace(hour=0, minute=0, second=0, microsecond=0) end_timestamp = start_timestamp + timedelta(days=1) events = events.filter((Event.start_time <= end_timestamp) & (Event.end_time >= start_timestamp)) \ .order_by('start_time', 'end_time') if user is None: events = events.filter(Event.visibility == EventVisibility.public) else: events = events.filter((Event.visibility == EventVisibility.public) | (Event.profile == user.profile) | (Invitation.invitee == user.profile) | (Response.profile == user.profile)) return events