doneth.at/app/days.py

93 lines
2.8 KiB
Python

from datetime import datetime, timedelta, timezone
import pytz
def _suffix(d):
return 'th' if 11 <= d <= 13 else {1: 'st', 2: 'nd', 3: 'rd'}.get(d % 10, 'th')
class Day:
def __init__(self, year, month, day, user):
self.user = user
self._timestamp = datetime(year, month, day, tzinfo=timezone.utc)
@staticmethod
def from_str(string, user):
return Day._from_timestamp(datetime.strptime(string, "%Y-%m-%d"), user)
@staticmethod
def _from_timestamp(timestamp, user):
# not exposed because it is only an utilty function, not aware of the
# user's time zone and start-of-day hour
return Day(timestamp.year, timestamp.month, timestamp.day, user)
def __eq__(self, other):
if not isinstance(other, self.__class__):
return False
return self.year == other.year \
and self.month == other.month \
and self.day == other.day
def __add__(self, other, oper="+"):
if not isinstance(other, int):
raise TypeError(
'Unsupported operands for "+". The right hand side needs to be a number.')
else:
return Day._from_timestamp(self.timestamp + timedelta(days=other), self.user)
def __sub__(self, other):
if not isinstance(other, int):
raise TypeError(
'Unsupported operands for "-". The right hand side needs to be a number.')
else:
return Day._from_timestamp(self.timestamp + timedelta(days=-other), self.user)
def __lt__(self, other): return self.timestamp < other.timestamp
def __gt__(self, other): return self.timestamp > other.timestamp
def __le__(self, other): return self < other or self == other
def __ge__(self, other): return self > other or self == other
def __repr__(self): return "<Day[%s,user=%s]>" % (self.url, self.user)
@property
def year(self): return self._timestamp.year
@property
def month(self): return self._timestamp.month
@property
def day(self): return self._timestamp.day
@property
def timestamp(self): return self._timestamp
@property
def is_today(self):
return self == Day.today(self.user)
@property
def is_future(self):
return self > Day.today(self.user)
@property
def pretty(self):
if self.is_today:
return "Today"
return self._timestamp.strftime("%B {S}, %Y").replace('{S}', str(self.day) + _suffix(self.day))
@property
def url(self):
return self._timestamp.strftime("%Y-%m-%d")
@staticmethod
def today(user):
tz = pytz.timezone(user.timezone)
now = datetime.now(tz)
day = Day(now.year, now.month, now.day, user)
if now.hour < user.start_of_day:
day -= 1
return day