Skip to content

Commit 0ca02aa

Browse files
refactor: accept tz name in timezone util methods and refactor iana-changes-updates script (ietf-tools#4444)
* refactor: accept tz name strings in ietf.utils.timezone methods * refactor: use explicitly tz-aware math for iana-changes-updates script * chore: remove unused "local_timezone_to_utc()" method helper
1 parent 54c57e0 commit 0ca02aa

3 files changed

Lines changed: 38 additions & 31 deletions

File tree

ietf/bin/iana-changes-updates

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ django.setup()
1818

1919
from django.conf import settings
2020
from optparse import OptionParser
21+
from zoneinfo import ZoneInfo
2122

2223
parser = OptionParser()
2324
parser.add_option("-f", "--from", dest="start",
@@ -38,21 +39,30 @@ CLOCK_SKEW_COMPENSATION = 5 # seconds
3839
MAX_INTERVAL_ACCEPTED_BY_IANA = datetime.timedelta(hours=23)
3940

4041

42+
local_tzinfo = ZoneInfo(settings.TIME_ZONE)
4143
start = datetime.datetime.now() - datetime.timedelta(hours=23) + datetime.timedelta(seconds=CLOCK_SKEW_COMPENSATION)
4244
if options.start:
4345
start = datetime.datetime.strptime(options.start, "%Y-%m-%d %H:%M:%S")
46+
start = start.replace(tzinfo=local_tzinfo).astimezone(datetime.timezone.utc)
4447

4548
end = start + datetime.timedelta(hours=23)
4649
if options.end:
47-
end = datetime.datetime.strptime(options.end, "%Y-%m-%d %H:%M:%S")
50+
end = datetime.datetime.strptime(options.end, "%Y-%m-%d %H:%M:%S").replace(tzinfo=local_tzinfo)
51+
end = end.astimezone(datetime.timezone.utc)
4852

4953
syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER)
5054

5155
# ----------------------------------------------------------------------
5256

5357
from ietf.sync.iana import fetch_changes_json, parse_changes_json, update_history_with_changes
5458

55-
syslog.syslog("Updating history log with new changes from IANA from %s, period %s - %s" % (settings.IANA_SYNC_CHANGES_URL, start, end))
59+
syslog.syslog(
60+
"Updating history log with new changes from IANA from %s, period %s - %s" % (
61+
settings.IANA_SYNC_CHANGES_URL,
62+
start.astimezone(local_tzinfo),
63+
end.astimezone(local_tzinfo),
64+
)
65+
)
5666

5767
t = start
5868
while t < end:

ietf/sync/iana.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
from ietf.person.models import Person
2525
from ietf.utils.log import log
2626
from ietf.utils.mail import parseaddr, get_payload_text
27-
from ietf.utils.timezone import local_timezone_to_utc
2827

2928

3029
#PROTOCOLS_URL = "https://www.iana.org/protocols/"
@@ -67,8 +66,8 @@ def update_rfc_log_from_protocol_page(rfc_names, rfc_must_published_later_than):
6766

6867

6968
def fetch_changes_json(url, start, end):
70-
url += "?start=%s&end=%s" % (urlquote(local_timezone_to_utc(start).strftime("%Y-%m-%d %H:%M:%S")),
71-
urlquote(local_timezone_to_utc(end).strftime("%Y-%m-%d %H:%M:%S")))
69+
url += "?start=%s&end=%s" % (urlquote(start.astimezone(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S")),
70+
urlquote(end.astimezone(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S")))
7271
# HTTP basic auth
7372
username = "ietfsync"
7473
password = settings.IANA_SYNC_PASSWORD

ietf/utils/timezone.py

Lines changed: 24 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import pytz
21
import datetime
32

3+
from typing import Union
44
from zoneinfo import ZoneInfo
55

66
from django.conf import settings
@@ -19,60 +19,58 @@
1919
RPC_TZINFO = ZoneInfo('PST8PDT')
2020

2121

22-
def make_aware(dt, tzinfo):
22+
def _tzinfo(tz: Union[str, datetime.tzinfo, None]):
23+
"""Helper to convert a tz param into a tzinfo
24+
25+
Accepts Defaults to UTC.
26+
"""
27+
if tz is None:
28+
return datetime.timezone.utc
29+
elif isinstance(tz, datetime.tzinfo):
30+
return tz
31+
else:
32+
return ZoneInfo(tz)
33+
34+
35+
def make_aware(dt, tz):
2336
"""Assign timezone to a naive datetime
2437
2538
Helper to deal with both pytz and zoneinfo type time zones. Can go away when pytz is removed.
2639
"""
40+
tzinfo = _tzinfo(tz)
2741
if hasattr(tzinfo, 'localize'):
2842
return tzinfo.localize(dt) # pytz-style
2943
else:
3044
return dt.replace(tzinfo=tzinfo) # zoneinfo- / datetime.timezone-style
3145

3246

33-
def local_timezone_to_utc(d):
34-
"""Takes a naive datetime in the local timezone and returns a
35-
naive datetime with the corresponding UTC time."""
36-
local_timezone = pytz.timezone(settings.TIME_ZONE)
37-
38-
d = local_timezone.localize(d).astimezone(pytz.utc)
39-
40-
return d.replace(tzinfo=None)
41-
42-
43-
def datetime_from_date(date, tz=pytz.utc):
47+
def datetime_from_date(date, tz=None):
4448
"""Get datetime at midnight on a given date"""
4549
# accept either pytz or zoneinfo tzinfos until we get rid of pytz
46-
return make_aware(datetime.datetime(date.year, date.month, date.day), tz)
50+
return make_aware(datetime.datetime(date.year, date.month, date.day), _tzinfo(tz))
4751

4852

49-
def datetime_today(tzinfo=None):
53+
def datetime_today(tz=None):
5054
"""Get a timezone-aware datetime representing midnight today
5155
5256
For use with datetime fields representing a date.
5357
"""
54-
if tzinfo is None:
55-
tzinfo = pytz.utc
56-
return timezone.now().astimezone(tzinfo).replace(hour=0, minute=0, second=0, microsecond=0)
58+
return timezone.now().astimezone(_tzinfo(tz)).replace(hour=0, minute=0, second=0, microsecond=0)
5759

5860

59-
def date_today(tzinfo=None):
61+
def date_today(tz=None):
6062
"""Get the date corresponding to the current moment
6163
6264
Note that Dates are not themselves timezone aware.
6365
"""
64-
if tzinfo is None:
65-
tzinfo = pytz.utc
66-
return timezone.now().astimezone(tzinfo).date()
66+
return timezone.now().astimezone(_tzinfo(tz)).date()
6767

6868

69-
def time_now(tzinfo=None):
69+
def time_now(tz=None):
7070
"""Get the "wall clock" time corresponding to the current moment
7171
7272
The value returned by this data is a Time with no tzinfo attached. (Time
7373
objects have only limited timezone support, even if tzinfo is filled in,
7474
and may not behave correctly when daylight savings time shifts are relevant.)
7575
"""
76-
if tzinfo is None:
77-
tzinfo = pytz.utc
78-
return timezone.now().astimezone(tzinfo).time()
76+
return timezone.now().astimezone(_tzinfo(tz)).time()

0 commit comments

Comments
 (0)