forked from gergely/calendar-social
Gergely Polonkai
a862e6ca5d
This shows if the event is visible to anyone or just people who are invited. The calendar view already respects this flag.
230 lines
6.5 KiB
Python
230 lines
6.5 KiB
Python
# 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 <https://www.gnu.org/licenses/>.
|
||
|
||
"""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, 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 >= start_timestamp) &
|
||
(Event.start_time < end_timestamp)) |
|
||
((Event.end_time >= start_timestamp) &
|
||
(Event.end_time < end_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
|