File size: 5,342 Bytes
550665c |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 |
from datetime import time, date, datetime
from typing import Union
from beautiful_date import BeautifulDate, days
class Reminder:
def __init__(
self,
method: str,
minutes_before_start: int = None,
days_before: int = None,
at: time = None
):
"""Represents base reminder object
Provide `minutes_before_start` to create "relative" reminder.
Provide `days_before` and `at` to create "absolute" reminder.
:param method:
Method of the reminder. Possible values: email or popup
:param minutes_before_start:
Minutes before reminder
:param days_before:
Days before reminder
:param at:
Specific time for a reminder
"""
# Nothing was provided
if minutes_before_start is None and days_before is None and at is None:
raise ValueError("Relative reminder needs 'minutes_before_start'. "
"Absolute reminder 'days_before' and 'at' set. "
"None of them were provided.")
# Both minutes_before_start and days_before/at were provided
if minutes_before_start is not None and (days_before is not None or at is not None):
raise ValueError("Only minutes_before_start or days_before/at can be specified.")
# Only one of days_before and at was provided
if (days_before is None) != (at is None):
raise ValueError(f'Both "days_before" and "at" values need to be set '
f'when using absolute time for a reminder. '
f'Provided days_before={days_before} and at={at}.')
self.method = method
self.minutes_before_start = minutes_before_start
self.days_before = days_before
self.at = at
def __eq__(self, other):
return (
isinstance(other, Reminder)
and self.method == other.method
and self.minutes_before_start == other.minutes_before_start
and self.days_before == other.days_before
and self.at == other.at
)
def __str__(self):
if self.minutes_before_start is not None:
return '{} - minutes_before_start:{}'.format(self.__class__.__name__, self.minutes_before_start)
else:
return '{} - {} days before at {}'.format(self.__class__.__name__, self.days_before, self.at)
def __repr__(self):
return '<{}>'.format(self.__str__())
def convert_to_relative(self, start: Union[date, datetime, BeautifulDate]) -> 'Reminder':
"""Converts absolute reminder (with set `days_before` and `at`) to relative (with set `minutes_before_start`)
relative to `start` date/datetime. Returns self if `minutes_before_start` already set.
"""
if self.minutes_before_start is not None:
return self
tzinfo = start.tzinfo if isinstance(start, datetime) else None
start_of_the_day = datetime.combine(start, datetime.min.time(), tzinfo=tzinfo)
reminder_tzinfo = self.at.tzinfo or tzinfo
reminder_time = datetime.combine(start_of_the_day - self.days_before * days, self.at, tzinfo=reminder_tzinfo)
if isinstance(start, datetime):
minutes_before_start = int((start - reminder_time).total_seconds() / 60)
else:
minutes_before_start = int((start_of_the_day - reminder_time).total_seconds() / 60)
return Reminder(
method=self.method,
minutes_before_start=minutes_before_start
)
class EmailReminder(Reminder):
def __init__(
self,
minutes_before_start: int = None,
days_before: int = None,
at: time = None
):
"""Represents email reminder object
Provide `minutes_before_start` to create "relative" reminder.
Provide `days_before` and `at` to create "absolute" reminder.
:param minutes_before_start:
Minutes before reminder
:param days_before:
Days before reminder
:param at:
Specific time for a reminder
"""
if not days_before and not at and not minutes_before_start:
minutes_before_start = 60
super().__init__('email', minutes_before_start, days_before, at)
class PopupReminder(Reminder):
def __init__(
self,
minutes_before_start: int = None,
days_before: int = None,
at: time = None
):
"""Represents popup reminder object
Provide `minutes_before_start` to create "relative" reminder.
Provide `days_before` and `at` to create "absolute" reminder.
:param minutes_before_start:
Minutes before reminder
:param days_before:
Days before reminder
:param at:
Specific time for a reminder
"""
if not days_before and not at and not minutes_before_start:
minutes_before_start = 30
super().__init__('popup', minutes_before_start, days_before, at)
|