-
Notifications
You must be signed in to change notification settings - Fork 0
/
wait.py
116 lines (97 loc) · 3.18 KB
/
wait.py
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
"""
Util functions to wait for time to post notifications.
"""
import time
from datetime import datetime, timedelta, timezone
from typing import Optional
TimeSeconds = float
Datetime = datetime
# offset from UTC to JST
TIMEZONE_OFFSET = (timedelta(hours=9) - timedelta(hours=0)).seconds
def wait_until(
then: Optional[Datetime] = None,
*,
day=None, hour=0, minute=0, second=0,
_how_to_know_now=None,
_sleep=time.sleep,
_debug=print,
) -> None:
"""Wait until a specific time point. Default to 0:00 on the next day.
Args:
then (Optional[Datetime], optional): Defaults to None.
day (Optional[int], optional): Defaults to today.
hour (int, optional): Defaults to 0.
minute (int, optional): Defaults to 0.
second (int, optional): Defaults to 0.
_how_to_know_now (optional): Defaults to None.
_sleep (optional): Defaults to time.sleep.
_debug (optional): Defaults to print.
>>> now = Datetime.now(tz=timezone(timedelta(hours=+9)))
>>> wait_until(
... hour=now.hour, minute=now.minute, second=now.second,
... _sleep=(lambda _: None),
... _how_to_know_now=(lambda: Datetime.now(tz=timezone(timedelta(hours=0)))),
... )
Wait for 0.0 sec(s).
"""
duration = compute_duration_to_tomorrow(
then=then,
day=day,
hour=hour,
minute=minute,
second=second,
# for debugging
how_to_know_now=_how_to_know_now if _how_to_know_now else Datetime.now,
)
duration = duration - TIMEZONE_OFFSET
if duration < 0.0:
duration += 24 * 60 * 60.0
_debug(f"Wait for {duration} sec(s).")
_sleep(duration)
def compute_duration_to_tomorrow(
then: Optional[Datetime] = None,
*,
how_to_know_now=Datetime.now,
**kwargs
) -> TimeSeconds:
"""
>>> now = Datetime(year=2020, month=6, day=15, hour=0)
>>> duration_to_tomorrow = compute_duration_to_tomorrow(
... how_to_know_now=(lambda: now),
... day=now.day, hour=1,
... )
>>> duration_to_yesterday = compute_duration_to_tomorrow(
... how_to_know_now=(lambda: now),
... day=(now.day-1), hour=1,
... )
>>> int(duration_to_yesterday) == int(duration_to_tomorrow)
True
"""
if then is None and len(kwargs) == 0:
raise ValueError("Any of `datetime` properties should be specified.")
now = how_to_know_now()
if then is None:
if kwargs["day"] is None:
kwargs["day"] = now.day
then: Datetime = now.replace(**kwargs)
duration = differ_from(now=now, then=then)
if duration < 0.0:
duration += 24 * 60 * 60.0
return duration
def differ_from(*, now: Datetime, then: Datetime) -> TimeSeconds:
"""
>>> now = Datetime.now()
>>> duration = differ_from(now=now, then=now)
>>> int(duration)
0
>>> tomorrow = now.replace(day=(now.day + 1))
>>> duration = differ_from(now=now, then=tomorrow)
>>> int(duration)
86400
>>> yesterday = now.replace(day=(now.day - 1))
>>> duration = differ_from(now=now, then=yesterday)
>>> int(duration)
-86400
"""
duration = (then - now).total_seconds()
return duration