Created
July 24, 2020 18:33
-
-
Save cbogart/d3952bdc8b24a2b487deac84ce01d83a to your computer and use it in GitHub Desktop.
Moving a list of times forward a few months, taking into account daylight savings, and maybe a new timezone
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import datetime | |
import pytz | |
# Note pytz is not standard python library, but there | |
# are no standard timezone classes before Python 3.2!! | |
# This is Python 2.7 code. | |
source_timezone = "America/New_York" | |
destination_timezone = "America/New_York" | |
# There are 2 kinds of dates: | |
# Naive dates just have date and time, and we have no idea what time zone they represent, | |
# unless we know from context somehow | |
# Timezoned dates have a time zone associated. We can convert to other timezones, and | |
# the hours (and sometimes minutes) change, but also the zone changes | |
# We typically store dates timezoned, in UTC as the timezone. | |
# This exercise demos taking UTC dates for events that happened in Pittsburgh at midnight, | |
# converting them to timezoned Pittsburgh dates, then making them naive, so | |
# they all show up as midnight dates. | |
# Then we shift them forward a few weeks | |
# Then force them to be pittsburgh timezone-aware dates again, | |
# Then finally shift back to UTC to be standard. | |
# Suppose we have a list of module start and end dates; these are | |
# stored internally as UTC. If you call, for example | |
# Course.objects.get(slug="f16-15319").start_time, you'll | |
# get an object of type datetime.datetime, that is timezone-aware, | |
# with timezone set to UTC | |
# Example has two pittsburgh-midnight dates before, and two after | |
# the time change | |
original_module_dates_utc = \ | |
[datetime.datetime(2020,1,1,5,0,0, tzinfo=pytz.utc), | |
datetime.datetime(2020,1,7,5,0,0, tzinfo=pytz.utc), | |
datetime.datetime(2020,7,1,4,0,0, tzinfo=pytz.utc), | |
datetime.datetime(2020,7,7,4,0,0, tzinfo=pytz.utc)] | |
# | |
# Note: never do datetime(...tzinfo=pytz.<something other than UTC>); this will not handle dst correctly | |
# see http://pytz.sourceforge.net/ | |
# | |
print("Original dates as UTC") | |
for o in original_module_dates_utc: | |
print(o) | |
# | |
# Convert from UTC to local time, naive | |
def utc2local_naive_tz(t, the_tz): | |
t_naive = t.astimezone(pytz.timezone(the_tz)) | |
t_naive = t_naive.replace(tzinfo=None) | |
return t_naive | |
print("Original dates as local, naive, assuming they happened in ", source_timezone) | |
original_dates_as_pgh_local_naive = \ | |
[utc2local_naive_tz(t, source_timezone) for t in original_module_dates_utc] | |
for o in original_dates_as_pgh_local_naive: | |
print(o) | |
# | |
# Offset the dates without affecting the times, so that | |
# the translation ignores daylight savings changes | |
print("new dates as local, naive") | |
def addweeks(t,w): | |
return t + datetime.timedelta(days=w*7) | |
new_dates_as_pgh_local_naive = \ | |
[addweeks(t,25) for t in original_dates_as_pgh_local_naive] | |
for n in new_dates_as_pgh_local_naive: | |
print(n) | |
# | |
# Convert back to UTC | |
# | |
def naive2utc_assuming_tz(t, dest): | |
t_utc = pytz.timezone(dest).localize(t) | |
t_utc = t_utc.astimezone(pytz.utc) | |
return t_utc | |
new_dates_as_utc = \ | |
[naive2utc_assuming_tz(t,destination_timezone) | |
for t in new_dates_as_pgh_local_naive] | |
print("assuming those times were " + destination_timezone + ", convert back to utc") | |
for n in new_dates_as_utc: | |
print(n) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment