|
| 1 | + |
| 2 | +""" |
| 3 | +calculate the amount of seconds until the next duck thursday |
| 4 | +""" |
| 5 | + |
| 6 | +# TODO: |
| 7 | +# - get current time datetime.now |
| 8 | +# - configure next duck thursday |
| 9 | +# - duck thursday - now |
| 10 | +# - arg parse |
| 11 | + |
| 12 | +import datetime |
| 13 | +import typing |
| 14 | +import unittest |
| 15 | + |
| 16 | + |
| 17 | +def get_current_time(): |
| 18 | + ctime = datetime.datetime.now() |
| 19 | + return ctime |
| 20 | + |
| 21 | +WEEKDAY_LOOKUP: dict[int, str] = { 0 : "Monday", 1 : "Tuesday", 2: "Wednesday", 3: "Thursday", 4 : "Friday", 5 : "Saturday", 6: "Sunday" } |
| 22 | + |
| 23 | +class Duck_Thursday_Config: |
| 24 | + def __init__(self, option: typing.Callable | list[datetime.datetime]): |
| 25 | + self.pattern = option if isinstance(option, typing.Callable) else None |
| 26 | + self.duck_thursdays = option if isinstance(option, list) else None |
| 27 | + assert(self.pattern is not None or self.duck_thursdays is not None) |
| 28 | + |
| 29 | + def is_duck_thursday(self, to_check :datetime.datetime) : |
| 30 | + if self.pattern is not None: |
| 31 | + return self.pattern(to_check) |
| 32 | + |
| 33 | +def get_days_until_next_duck_thurdsay(config: Duck_Thursday_Config | None = None) -> datetime.datetime : |
| 34 | + """Gets the next duck thursday (from today)""" |
| 35 | + if config is None: |
| 36 | + duck_thursday = 3 |
| 37 | + weekday = get_current_time().weekday() |
| 38 | + # 3 - 1 => 2 Monday (2) 2 => 9 2 % 7 => 2 |
| 39 | + # 3 - 4 => -1 Friday (6) -1 => 6 -1 % 7 => 6 |
| 40 | + return (duck_thursday - weekday) % 7 |
| 41 | + current = get_current_time(); |
| 42 | + if (config.pattern is not None): |
| 43 | + for _ in range(99999): |
| 44 | + current += datetime.timedelta(days=1) |
| 45 | + if config.is_duck_thursday(current): |
| 46 | + return current |
| 47 | + raise Exception("NO DUCk THURSDAY?!") |
| 48 | + if config.duck_thursdays is not None: |
| 49 | + for duck in config.duck_thursdays: |
| 50 | + if duck > get_current_time() + datetime.timedelta(days=1): # + 1 |
| 51 | + return duck |
| 52 | + raise Exception("NO DUCk THURSDAY?!") |
| 53 | + raise Exception("Config was not valid") |
| 54 | + |
| 55 | + |
| 56 | +def time_until_midnight(): |
| 57 | + midnight = datetime.datetime.combine(get_current_time().date(), datetime.time()) |
| 58 | + return midnight |
| 59 | + |
| 60 | +def time_at_start_of_day(the_day:datetime.datetime): |
| 61 | + midnight = datetime.datetime.combine(the_day.date(), datetime.time()) |
| 62 | + return midnight |
| 63 | + |
| 64 | +def get_next_duck_thursday() -> datetime.datetime: |
| 65 | + days_left = get_days_until_next_duck_thurdsay() |
| 66 | + # days left to duration |
| 67 | + days_left = datetime.timedelta(days=days_left) |
| 68 | + # add duration to now |
| 69 | + next_duck_thursday = days_left + datetime.datetime.now() |
| 70 | + # round to start of day |
| 71 | + next_duck_thursday = time_at_start_of_day(next_duck_thursday) |
| 72 | + # return that^ |
| 73 | + return next_duck_thursday |
| 74 | + |
| 75 | +def seconds_to_next_duck_thursday() -> int: |
| 76 | + duration = get_next_duck_thursday() - datetime.datetime.now() |
| 77 | + return duration.seconds |
| 78 | + |
| 79 | +def assert_no_throws(callable, *args): |
| 80 | + try: |
| 81 | + callable(*args) |
| 82 | + return True |
| 83 | + except: |
| 84 | + return False |
| 85 | + |
| 86 | +def assert_throws(callable, *args): |
| 87 | + try: |
| 88 | + callable(*args) |
| 89 | + return False |
| 90 | + except: |
| 91 | + return True |
| 92 | + |
| 93 | +if __name__ == "__main__": |
| 94 | + print("Hello duck world") |
| 95 | + print(time_until_midnight()) |
| 96 | + print(get_next_duck_thursday()) |
| 97 | + print(seconds_to_next_duck_thursday()) |
| 98 | + print(assert_throws(get_days_until_next_duck_thurdsay, Duck_Thursday_Config([]) )) |
| 99 | + print(assert_throws(get_days_until_next_duck_thurdsay, Duck_Thursday_Config( lambda a : False ) )) |
| 100 | + print(assert_no_throws(get_days_until_next_duck_thurdsay, Duck_Thursday_Config( lambda a : True ) )) |
| 101 | + print(get_days_until_next_duck_thurdsay( Duck_Thursday_Config( lambda a : a < datetime.datetime.now() + datetime.timedelta(days=1) ) )) |
| 102 | + |
| 103 | + |
| 104 | + |
0 commit comments