# 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 functools import wraps from flask_babelex import lazy_gettext as _ from . import CalendarSystem def to_timestamp(func): """Decorator that converts the return value of a function from `datetime` to a UNIX timestamp """ @wraps(func) def _decorator(*args, **kwargs): return func(*args, **kwargs).timestamp() return _decorator 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 = [] start_day = self.timestamp.replace(day=1) while start_day.weekday() > self.START_DAY: start_day -= timedelta(days=1) day_list.append(start_day) current_day = start_day while current_day.weekday() < self.END_DAY and current_day.month <= self.timestamp.month: current_day += timedelta(days=1) day_list.append(current_day) return day_list @property @to_timestamp 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 @to_timestamp 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 @to_timestamp 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 @to_timestamp 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 now >= month_start_timestamp and now < month_end_timestamp @staticmethod def day_events(date, user=None): """Returns all events for a given day """ from ..models import Event events = Event.query if user: events = events.filter(Event.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 >= start_timestamp) & (Event.start_time < end_timestamp)) | ((Event.end_time >= start_timestamp) & (Event.end_time < end_timestamp))) \ .order_by('start_time', 'end_time') return events