python - datetime with timezone to epoch

t0x13 picture t0x13 · Aug 28, 2012 · Viewed 24.7k times · Source

In the code below, I am calculating now epoch and beginning of current day epoch.

import time
import pytz
from datetime import datetime

tz1 = pytz.timezone('CST6CDT')
utc = pytz.timezone('UTC')
now = pytz.UTC.localize(datetime.utcnow())
now_tz = now.astimezone(tz1)
print now_tz
print now_tz.strftime('%s')

begin_day = now_tz.replace(hour=0, minute=0, second=0)
print begin_day

print begin_day.strftime('%s')

print statements:

2012-08-28 13:52:21.595718-05:00
1346187141
2012-08-28 00:00:00.595718-05:00
1346137200

Converting epochs to timestamp with CDT timezone: 1346187141 - Aug 28 2012 15:52:21, 1346137200 - Aug 28 2012 02:00:00

I'd like the second epoch to be beginning of the day but it's 2 am. It looks like it is still using local timezone PST when converting to epoch.

What am I doing wrong ? or can this be done a different way?

Thanks!

Answer

jfs picture jfs · Jun 23, 2013

To convert a datetime with timezone to epoch (POSIX timestamp):

from datetime import datetime
import pytz

tz = pytz.timezone('CST6CDT')

# a datetime with timezone
dt_with_tz = tz.localize(datetime(2012, 8, 28, 19, 33, 50), is_dst=None)

# get timestamp
ts = (dt_with_tz - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
# -> 1346200430.0

It is how datetime.timestamp method is implemented for timezone-aware datetime objects in Python 3.

To get "now epoch":

from datetime import datetime

now_epoch = (datetime.utcnow() - datetime(1970, 1, 1)).total_seconds()

Or (assuming time uses POSIX epoch):

import time

now_epoch = time.time()

Getting "beginning of current day epoch" is more complex because current day may be different in different timezones:

from datetime import datetime, time
import pytz

tz = pytz.timezone('CST6CDT')

# get current date in given timezone
today = datetime.now(tz).date()
# -> datetime.date(2013, 6, 22)

# get beginning of current day in given timezone as a datetime with timezone
midnight = tz.localize(datetime.combine(today, time(0, 0)), is_dst=None)
# -> datetime.datetime(2013, 6, 22, 0, 0, tzinfo=<DstTzInfo 'CST6CDT'...>)

# get timestamp
ts = (midnight - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()
# -> 1371877200.0 

See How do I get the UTC time of “midnight” for a given timezone?.

To get "beginning of current day epoch" assuming UTC date:

from datetime import datetime, date

# get current date in UTC
utc_date = datetime.utcnow().date()
# -> datetime.date(2013, 6, 23)

# get timestamp
ts = (utc_date - date(1970, 1, 1)).days * 86400
# -> 1371945600

See Converting datetime.date/datetime.datetime to UTC timestamp in Python.