python – datetime with timezone to epoch

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!

Answers:

Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.

Method 1

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.

Method 2

NOTE: My answer is flat-out wrong. (I’d like to delete it, but am unable to do so until the accept flag is removed.)

Please see J.F.Sebastian’s answer.

Here is code demonstrating a value of now_tz for which our two methods produce different results.

import calendar
import pytz
import datetime as dt

tz1 = pytz.timezone('US/Eastern')
utc = pytz.timezone('UTC')
now = utc.localize(dt.datetime(2002, 10, 28), is_dst=None)
now_tz = now.astimezone(tz1)
now_epoch = calendar.timegm(now_tz.utctimetuple())
begin_day = tz1.normalize(now_tz.replace(hour=0, minute=0, second=0))

midnight = tz1.localize(dt.datetime.combine(now_tz, dt.time(0, 0)), is_dst=None)
if begin_day != midnight:
    print(begin_day)
    # 2002-10-27 01:00:00-04:00  # my result -- is not midnight
    print(midnight)
    # 2002-10-27 00:00:00-04:00  # J.F.Sebastian's result is correct

(Original answer redacted)

Method 3

the latest release of simple-date (version 0.2 on pypi) will manage the details for you:

>>> from simpledate import *
>>> now_utc = SimpleDate(tz='UTC')
>>> now_tz = now_utc.convert(tz='CST6CDT')
>>> begin_day = now_tz.replace(hour=0, minute=0, second=0, microsecond=0)
>>> now_utc.timestamp
1371950295.777453
>>> now_tz.timestamp
1371950295.777453
>>> begin_day.timestamp
1371877200.0

we can go backwards to check the timestamps (although it’s clear above that switching timezone didn’t change the epoch, while moving to start of day did):

>>> SimpleDate(1371877200.0, tz='CST6CDT')
SimpleDate('2013-06-22 00:00:00.000000 CDT', tz='CST6CDT')
>>> SimpleDate(1371877200.0, tz='UTC')
SimpleDate('2013-06-22 05:00:00.000000 UTC')


All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

0 0 votes
Article Rating
Subscribe
Notify of
guest

0 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x