* refactor: replace datetime.now with timezone.now * refactor: migrate model fields to use timezone.now as default * refactor: replace datetime.today with timezone.now datetime.datetime.today() is equivalent to datetime.datetime.now(); both return a naive datetime with the current local time. * refactor: rephrase datetime.now(tz) as timezone.now().astimezone(tz) This is effectively the same, but is less likely to encourage accidental use of naive datetimes. * refactor: revert datetime.today() change to old migrations * refactor: change a missed datetime.now to timezone.now * chore: renumber timezone_now migration * chore: add migration to change timestamps to UTC * refactor: move tz instantiation/caching from TimeSlot to Meeting * fix: assume utc if meeting.time_zone is blank * chore: make datetime.combine() calls tz aware in the meeting app * ci: correctly use meeting.tz in TimeSlotFactory * chore: compute TimeSlot utc / local times assuming tz-aware times * chore: use tzaware math for agenda editor timeslot layout * chore: fill in Meeting.time_zone where it is blank Nearly all interim meetings on or before 2016-07-01 have blank time_zone values. This migration fills these in with PST8PDT. * chore: disallow blank Meeting.time_zone value * refactor: no need to handle blank time_zone case in TZ migration * refactor: remove now-unnecessary checks that meeting has time_zone * chore: fix timezone handling in agenda.ics and Meeting.updated() * chore: fix tz handling in interim_request_details, exercise in tests * chore: fix timezone handling for test_interim_send_announcement * chore: fix timezone handling in agenda_json() * chore: fix timezone handling in old agenda * chore: fix timezone handling for EditTimeslotsTests * refactor: refactor a few fixes for more consistent timezone handling * chore: add timezone info to timestamps in fixtures * chore: remove naive datetime warnings found in meetings.tests_views * chore: fix a few more test failures in meetings.tests_views All tests in meetings.tests_views now passing * chore: remove unused import * chore: fix timezone handling in test_schedule_generator.py * chore: fix timezone handling affecting meeting.tests_js * chore: fix timeslot test bug when local date != UTC date * test: fix a few failing tests, all meetings tests now pass (for me, anyway) * chore: renumber migrations * chore: update timestamp conversion migration The django-celery-beat package introduces tables with timestamp columns. These columns are stored in CELERY_TIMEZONE. Because we run with this set to UTC, the migration ignores these columns. * chore: fix pytz-related change in migration * chore: remove duplicate migrations * chore: remove CELERY_BEAT_TZ_AWARE setting now that USE_TZ is True * test: avoid failure in test with bogus timezone
72 lines
2.1 KiB
Python
72 lines
2.1 KiB
Python
import pytz
|
|
import email.utils
|
|
import datetime
|
|
|
|
from django.conf import settings
|
|
from django.utils import timezone
|
|
|
|
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 utc_to_local_timezone(d):
|
|
"""Takes a naive datetime UTC and returns a naive datetime in the
|
|
local time zone."""
|
|
local_timezone = pytz.timezone(settings.TIME_ZONE)
|
|
|
|
d = local_timezone.normalize(d.replace(tzinfo=pytz.utc).astimezone(local_timezone))
|
|
|
|
return d.replace(tzinfo=None)
|
|
|
|
def email_time_to_local_timezone(date_string):
|
|
"""Takes a time string from an email and returns a naive datetime
|
|
in the local time zone."""
|
|
|
|
t = email.utils.parsedate_tz(date_string)
|
|
d = datetime.datetime(*t[:6])
|
|
|
|
if t[7] != None:
|
|
d += datetime.timedelta(seconds=t[9])
|
|
|
|
return utc_to_local_timezone(d)
|
|
|
|
def date2datetime(date, tz=pytz.utc):
|
|
return datetime.datetime(*(date.timetuple()[:6]), tzinfo=tz)
|
|
|
|
|
|
def datetime_today(tzinfo=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)
|
|
|
|
|
|
def date_today(tzinfo=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()
|
|
|
|
|
|
def time_now(tzinfo=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()
|