I've got a black-magic question about timezones.
I have an application where I need timestamped event. I store everything in UTC. However, I want to display (client-side) the date, neither in the user locale nor in UTC, but in a given timezone (namely, the Paris timezone).
Since there is no javascript way to do it easily (we would have to know the exact daylight saving time events using something like timezone.js which seems overkill), I wanted to do the following trick:
dutc=datetime(…,<UTC>)
dparis=datetime(…,<Paris>)
However, I don't get back my original timestamp
import datetime
import time
import pytz
utc = pytz.UTC
paris = pytz.timezone('Europe/Paris')
t = 1372982409 # timestamp in UTC
dutc = datetime.datetime.fromtimestamp(t, utc) # date in UTC
# datetime.datetime(2013, 7, 5, 0, 0, 9, tzinfo=<UTC>)
dparis = datetime.datetime.fromtimestamp(t, paris) # date in Paris time
# datetime.datetime(2013, 7, 5, 2, 0, 9, tzinfo=<DstTzInfo 'Europe/Paris' CEST+2:0
0:00 DST>)
dparisasutc = dparis.replace(tzinfo=utc) # force the date in UTC time
# datetime.datetime(2013, 7, 5, 2, 0, 9, tzinfo=<UTC>)
t0 = time.mktime(dparisasutc.timetuple())
# 1372986009.0
datetime.datetime.fromtimestamp(t0)
# datetime.datetime(2013, 7, 5, 3, 0, 9) # why not 02:00:09?
You wanted to:
- get the UTC date dutc=datetime(…,)
- convert it to paris date dparis=datetime(…,)
Ok, I'm with you so far, but then...
- force the tzinfo back to UTC to get an UTC timestamp corresponding to the date & time in Paris (eg. the same numerical date & time, but with UTC rather than Paris, without adding or removing hours)
- storing this UTC date as a timestamp so the client could parse it as a "fake UTC " timestamp, and display the "fake time "
This might be a bad idea. The general convention is that at timestamp represented as an integer is always based on UTC. This holds true almost everywhere (with certain Microsoft .Net types being the exception).
Since you're client is in JavaScript, they would expect any integer to be the number of milliseconds since 1/1/1970 UTC. Changing that will have some strange consequences. The most interesting one is that you will get the user's own local time zone's rules about daylight saving time to be applied erroneously. These can be excruciatingly difficult to find in testing.
The simplest answer to to not use the Date
type in JavaScript at all. Do the conversion to Paris time completely on the server, and pass a well-formatted string back to the browser.
A more interesting solution would be to pass the UTC time, either in an integer or as an ISO8601 string like 2013-08-21T17:29:00Z
. On the client, use a library that can recognize the UTC time and convert it to the Europe/Paris
zone. You mentioned not wanting to do this using timezone.js, but there are several other libraries to choose from. Some are very small, and let you include just the date for the zones you care about.
For example, try moment.js with the moment-timezone addon. You can specifically build a moment-timezone-data.js file containing only the Europe/Paris
zone data. (They have a nice interactive data builder on that site for this.)