refactor: accept tz name in timezone util methods and refactor iana-changes-updates script (#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
This commit is contained in:
Jennifer Richards 2022-09-13 13:16:36 -03:00 committed by GitHub
parent 54c57e0419
commit 0ca02aad1f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 38 additions and 31 deletions

View file

@ -18,6 +18,7 @@ django.setup()
from django.conf import settings
from optparse import OptionParser
from zoneinfo import ZoneInfo
parser = OptionParser()
parser.add_option("-f", "--from", dest="start",
@ -38,13 +39,16 @@ CLOCK_SKEW_COMPENSATION = 5 # seconds
MAX_INTERVAL_ACCEPTED_BY_IANA = datetime.timedelta(hours=23)
local_tzinfo = ZoneInfo(settings.TIME_ZONE)
start = datetime.datetime.now() - datetime.timedelta(hours=23) + datetime.timedelta(seconds=CLOCK_SKEW_COMPENSATION)
if options.start:
start = datetime.datetime.strptime(options.start, "%Y-%m-%d %H:%M:%S")
start = start.replace(tzinfo=local_tzinfo).astimezone(datetime.timezone.utc)
end = start + datetime.timedelta(hours=23)
if options.end:
end = datetime.datetime.strptime(options.end, "%Y-%m-%d %H:%M:%S")
end = datetime.datetime.strptime(options.end, "%Y-%m-%d %H:%M:%S").replace(tzinfo=local_tzinfo)
end = end.astimezone(datetime.timezone.utc)
syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER)
@ -52,7 +56,13 @@ syslog.openlog(os.path.basename(__file__), syslog.LOG_PID, syslog.LOG_USER)
from ietf.sync.iana import fetch_changes_json, parse_changes_json, update_history_with_changes
syslog.syslog("Updating history log with new changes from IANA from %s, period %s - %s" % (settings.IANA_SYNC_CHANGES_URL, start, end))
syslog.syslog(
"Updating history log with new changes from IANA from %s, period %s - %s" % (
settings.IANA_SYNC_CHANGES_URL,
start.astimezone(local_tzinfo),
end.astimezone(local_tzinfo),
)
)
t = start
while t < end:

View file

@ -24,7 +24,6 @@ from ietf.doc.utils import add_state_change_event
from ietf.person.models import Person
from ietf.utils.log import log
from ietf.utils.mail import parseaddr, get_payload_text
from ietf.utils.timezone import local_timezone_to_utc
#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):
def fetch_changes_json(url, start, end):
url += "?start=%s&end=%s" % (urlquote(local_timezone_to_utc(start).strftime("%Y-%m-%d %H:%M:%S")),
urlquote(local_timezone_to_utc(end).strftime("%Y-%m-%d %H:%M:%S")))
url += "?start=%s&end=%s" % (urlquote(start.astimezone(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S")),
urlquote(end.astimezone(datetime.timezone.utc).strftime("%Y-%m-%d %H:%M:%S")))
# HTTP basic auth
username = "ietfsync"
password = settings.IANA_SYNC_PASSWORD

View file

@ -1,6 +1,6 @@
import pytz
import datetime
from typing import Union
from zoneinfo import ZoneInfo
from django.conf import settings
@ -19,60 +19,58 @@ DEADLINE_TZINFO = ZoneInfo('PST8PDT')
RPC_TZINFO = ZoneInfo('PST8PDT')
def make_aware(dt, tzinfo):
def _tzinfo(tz: Union[str, datetime.tzinfo, None]):
"""Helper to convert a tz param into a tzinfo
Accepts Defaults to UTC.
"""
if tz is None:
return datetime.timezone.utc
elif isinstance(tz, datetime.tzinfo):
return tz
else:
return ZoneInfo(tz)
def make_aware(dt, tz):
"""Assign timezone to a naive datetime
Helper to deal with both pytz and zoneinfo type time zones. Can go away when pytz is removed.
"""
tzinfo = _tzinfo(tz)
if hasattr(tzinfo, 'localize'):
return tzinfo.localize(dt) # pytz-style
else:
return dt.replace(tzinfo=tzinfo) # zoneinfo- / datetime.timezone-style
def local_timezone_to_utc(d):
"""Takes a naive datetime in the local timezone and returns a
naive datetime with the corresponding UTC time."""
local_timezone = pytz.timezone(settings.TIME_ZONE)
d = local_timezone.localize(d).astimezone(pytz.utc)
return d.replace(tzinfo=None)
def datetime_from_date(date, tz=pytz.utc):
def datetime_from_date(date, tz=None):
"""Get datetime at midnight on a given date"""
# accept either pytz or zoneinfo tzinfos until we get rid of pytz
return make_aware(datetime.datetime(date.year, date.month, date.day), tz)
return make_aware(datetime.datetime(date.year, date.month, date.day), _tzinfo(tz))
def datetime_today(tzinfo=None):
def datetime_today(tz=None):
"""Get a timezone-aware datetime representing midnight today
For use with datetime fields representing a date.
"""
if tzinfo is None:
tzinfo = pytz.utc
return timezone.now().astimezone(tzinfo).replace(hour=0, minute=0, second=0, microsecond=0)
return timezone.now().astimezone(_tzinfo(tz)).replace(hour=0, minute=0, second=0, microsecond=0)
def date_today(tzinfo=None):
def date_today(tz=None):
"""Get the date corresponding to the current moment
Note that Dates are not themselves timezone aware.
"""
if tzinfo is None:
tzinfo = pytz.utc
return timezone.now().astimezone(tzinfo).date()
return timezone.now().astimezone(_tzinfo(tz)).date()
def time_now(tzinfo=None):
def time_now(tz=None):
"""Get the "wall clock" time corresponding to the current moment
The value returned by this data is a Time with no tzinfo attached. (Time
objects have only limited timezone support, even if tzinfo is filled in,
and may not behave correctly when daylight savings time shifts are relevant.)
"""
if tzinfo is None:
tzinfo = pytz.utc
return timezone.now().astimezone(tzinfo).time()
return timezone.now().astimezone(_tzinfo(tz)).time()