python - the - whatwg developers




How do I get the UTC time of “midnight” for a given timezone? (3)

@hop's answer is wrong on the day of transition from Daylight Saving Time (DST) e.g., Apr 1, 2012. To fix it tz.localize() could be used:

tz = pytz.timezone("Australia/Melbourne")
today = datetime.now(tz).date()
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
utc_dt = midnight.astimezone(pytz.utc)        

The same with comments:

#!/usr/bin/env python
from datetime import datetime, time
import pytz # pip instal pytz

tz = pytz.timezone("Australia/Melbourne") # choose timezone

# 1. get correct date for the midnight using given timezone.
today = datetime.now(tz).date()

# 2. get midnight in the correct timezone (taking into account DST)
#NOTE: tzinfo=None and tz.localize()
# assert that there is no dst transition at midnight (`is_dst=None`)
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)

# 3. convert to UTC (no need to call `utc.normalize()` due to UTC has no 
#    DST transitions)
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
print midnight.astimezone(pytz.utc).strftime(fmt)

The best I can come up with for now is this monstrosity:

>>> datetime.utcnow() \
...   .replace(tzinfo=pytz.UTC) \
...   .astimezone(pytz.timezone("Australia/Melbourne")) \
...   .replace(hour=0,minute=0,second=0,microsecond=0) \
...   .astimezone(pytz.UTC) \
...   .replace(tzinfo=None)
datetime.datetime(2008, 12, 16, 13, 0)

I.e., in English, get the current time (in UTC), convert it to some other timezone, set the time to midnight, then convert back to UTC.

I'm not just using now() or localtime() as that would use the server's timezone, not the user's timezone.

I can't help feeling I'm missing something, any ideas?


Each time zone has a number, eg US/Central = -6. This is defined as the offset in hours from UTC. Since 0000 is midnight, you can simply use this offset to find the time in any time zone when it is midnight UTC. To access that, I believe you can use

 time.timezone

According to The Python Docs, time.timezone actually gives the negative value of this number:

time.timezone

The offset of the local (non-DST) timezone, in seconds west of UTC (negative in most of Western Europe, positive in the US, zero in the UK).

So you would simply use that number for the time in hours if it's positive (i.e., if it's midnight in Chicago (which has a +6 timezone value), then it's 6000 = 6am UTC).

If the number is negative, subtract from 24. For example, Berlin would give -1, so 24 - 1 => 2300 = 11pm.


Setting the TZ environment variable modifies what timezone Python's date and time functions work with.

>>> time.gmtime()
(2008, 12, 17, 1, 16, 46, 2, 352, 0)
>>> time.localtime()
(2008, 12, 16, 20, 16, 47, 1, 351, 0)
>>> os.environ['TZ']='Australia/Melbourne'
>>> time.localtime()
(2008, 12, 17, 12, 16, 53, 2, 352, 1)




pytz