I'm trying to modify a datetime based on a timezone on save and on load the following way:
An input datetime, along with a input timezone are sent to the server and the server should update the datetime to reflect the timezone. So when it saves in the database (PostregSQL), the UTC time is saved (after the offset caused by the timezone, of course).
To reflect this here's a simpler example that fails in the same way:
Some imports:
>>> import datetime
>>> import pytz
>>> from apps.myapp.models import Project
Creating the two inputs:
>>> input_date = timezone.now()
>>> input_date
datetime.datetime(2017, 2, 7, 16, 7, 14, 377429, tzinfo=<UTC>)
>>> current_tz = pytz.timezone('America/New_York')
>>> current_tz
<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>
As you can see, the timezone is not 5h
(24 - 19 = 5
), but 4h56
. At this stage I'm thinking that's OK, it may be related to the Daylight Saving Time.
Now I'm replacing the timezone on the input date:
>>> input_date = input_date.replace(tzinfo=current_tz)
>>> input_date
datetime.datetime(2017, 2, 7, 16, 7, 14, 377429, tzinfo=<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>)
As expected, the time hasn't changed, but the timezone has, which is fine.
I'll assign this value to a project (the launch_date
is a DateTimeField
without any specific option):
>>> project = Project.objects.get(pk=1)
>>> project.launch_date
datetime.datetime(2017, 1, 14, 8, 53, 57, 241718, tzinfo=<UTC>)
>>> project.launch_date = input_date
>>> project.launch_date
datetime.datetime(2017, 2, 7, 16, 7, 14, 377429, tzinfo=<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>)
Now I'll save this into (and refresh from) the database, leaving Django/PostgreSQL do the maths:
>>> project.save()
>>> project.refresh_from_db()
>>> project.launch_date
datetime.datetime(2017, 2, 7, 21, 3, 14, 377429, tzinfo=<UTC>)
As expected the date is now 4h56 ahead of the previous date. I'm trying now to get back the local time:
>>> project.launch_date.astimezone(current_tz)
datetime.datetime(2017, 2, 7, 16, 3, 14, 377429, tzinfo=<DstTzInfo 'America/New_York' EST-1 day, 19:00:00 STD>)
>>> input_date
datetime.datetime(2017, 2, 7, 16, 7, 14, 377429, tzinfo=<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>)
This time, the offset is perfectly 5h. And I'm missing 4 minutes.
3 questions here:
- Where is this 4 minutes coming from?
- Why is
astimezone
not using the 4 minutes as well? - How can a datetime be converted to UTC, saved, loaded and converted back to local?