Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting datetime.date to UTC timestamp in Python

I am dealing with dates in Python and I need to convert them to UTC timestamps to be used inside Javascript. The following code does not work:

>>> d = datetime.date(2011,01,01)
>>> datetime.datetime.utcfromtimestamp(time.mktime(d.timetuple()))
datetime.datetime(2010, 12, 31, 23, 0)

Converting the date object first to datetime also does not help. I tried the example at this link from, but:

from pytz import utc, timezone
from datetime import datetime
from time import mktime
input_date = datetime(year=2011, month=1, day=15)

and now either:

mktime(utc.localize(input_date).utctimetuple())

or

mktime(timezone('US/Eastern').localize(input_date).utctimetuple())

does work.

So general question: how can I get a date converted to seconds since epoch according to UTC?

like image 773
Andreas Jung Avatar asked Jan 08 '12 13:01

Andreas Jung


People also ask

How do you convert datetime to UTC datetime in Python?

Use the pytz module, which comes with a full list of time zones + UTC. Figure out what the local timezone is, construct a timezone object from it, and manipulate and attach it to the naive datetime. Finally, use datetime. astimezone() method to convert the datetime to UTC.

How do you convert datetime to UTC?

To convert the time in a non-local time zone to UTC, use the TimeZoneInfo. ConvertTimeToUtc(DateTime, TimeZoneInfo) method. To convert a time whose offset from UTC is known, use the ToUniversalTime method. If the date and time instance value is an ambiguous time, this method assumes that it is a standard time.

How do you generate UTC time in Python?

Getting the UTC timestampUse the datetime. datetime. now() to get the current date and time. Then use tzinfo class to convert our datetime to UTC.


3 Answers

If d = date(2011, 1, 1) is in UTC:

>>> from datetime import datetime, date
>>> import calendar
>>> timestamp1 = calendar.timegm(d.timetuple())
>>> datetime.utcfromtimestamp(timestamp1)
datetime.datetime(2011, 1, 1, 0, 0)

If d is in local timezone:

>>> import time
>>> timestamp2 = time.mktime(d.timetuple()) # DO NOT USE IT WITH UTC DATE
>>> datetime.fromtimestamp(timestamp2)
datetime.datetime(2011, 1, 1, 0, 0)

timestamp1 and timestamp2 may differ if midnight in the local timezone is not the same time instance as midnight in UTC.

mktime() may return a wrong result if d corresponds to an ambiguous local time (e.g., during DST transition) or if d is a past(future) date when the utc offset might have been different and the C mktime() has no access to the tz database on the given platform. You could use pytz module (e.g., via tzlocal.get_localzone()) to get access to the tz database on all platforms. Also, utcfromtimestamp() may fail and mktime() may return non-POSIX timestamp if "right" timezone is used.


To convert datetime.date object that represents date in UTC without calendar.timegm():

DAY = 24*60*60 # POSIX day in seconds (exact value)
timestamp = (utc_date.toordinal() - date(1970, 1, 1).toordinal()) * DAY
timestamp = (utc_date - date(1970, 1, 1)).days * DAY

How can I get a date converted to seconds since epoch according to UTC?

To convert datetime.datetime (not datetime.date) object that already represents time in UTC to the corresponding POSIX timestamp (a float).

Python 3.3+

datetime.timestamp():

from datetime import timezone

timestamp = dt.replace(tzinfo=timezone.utc).timestamp()

Note: It is necessary to supply timezone.utc explicitly otherwise .timestamp() assume that your naive datetime object is in local timezone.

Python 3 (< 3.3)

From the docs for datetime.utcfromtimestamp():

There is no method to obtain the timestamp from a datetime instance, but POSIX timestamp corresponding to a datetime instance dt can be easily calculated as follows. For a naive dt:

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)

And for an aware dt:

timestamp = (dt - datetime(1970,1,1, tzinfo=timezone.utc)) / timedelta(seconds=1)

Interesting read: Epoch time vs. time of day on the difference between What time is it? and How many seconds have elapsed?

See also: datetime needs an "epoch" method

Python 2

To adapt the above code for Python 2:

timestamp = (dt - datetime(1970, 1, 1)).total_seconds()

where timedelta.total_seconds() is equivalent to (td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6 computed with true division enabled.

Example

from __future__ import division
from datetime import datetime, timedelta

def totimestamp(dt, epoch=datetime(1970,1,1)):
    td = dt - epoch
    # return td.total_seconds()
    return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6 

now = datetime.utcnow()
print now
print totimestamp(now)

Beware of floating-point issues.

Output

2012-01-08 15:34:10.022403
1326036850.02

How to convert an aware datetime object to POSIX timestamp

assert dt.tzinfo is not None and dt.utcoffset() is not None
timestamp = dt.timestamp() # Python 3.3+

On Python 3:

from datetime import datetime, timedelta, timezone

epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
timestamp = (dt - epoch) / timedelta(seconds=1)
integer_timestamp = (dt - epoch) // timedelta(seconds=1)

On Python 2:

# utc time = local time              - utc offset
utc_naive  = dt.replace(tzinfo=None) - dt.utcoffset()
timestamp = (utc_naive - datetime(1970, 1, 1)).total_seconds()
like image 127
jfs Avatar answered Oct 17 '22 13:10

jfs


For unix systems only:

>>> import datetime
>>> d = datetime.date(2011, 1, 1)
>>> d.strftime("%s")  # <-- THIS IS THE CODE YOU WANT
'1293832800'

Note 1: dizzyf observed that this applies localized timezones. Don't use in production.

Note 2: Jakub Narębski noted that this ignores timezone information even for offset-aware datetime (tested for Python 2.7).

like image 110
Ulf Aslak Avatar answered Oct 17 '22 14:10

Ulf Aslak


  • Assumption 1: You're attempting to convert a date to a timestamp, however since a date covers a 24 hour period, there isn't a single timestamp that represents that date. I'll assume that you want to represent the timestamp of that date at midnight (00:00:00.000).

  • Assumption 2: The date you present is not associated with a particular time zone, however you want to determine the offset from a particular time zone (UTC). Without knowing the time zone the date is in, it isn't possible to calculate a timestamp for a specific time zone. I'll assume that you want to treat the date as if it is in the local system time zone.

First, you can convert the date instance into a tuple representing the various time components using the timetuple() member:

dtt = d.timetuple() # time.struct_time(tm_year=2011, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=1, tm_isdst=-1)

You can then convert that into a timestamp using time.mktime:

ts = time.mktime(dtt) # 1293868800.0

You can verify this method by testing it with the epoch time itself (1970-01-01), in which case the function should return the timezone offset for the local time zone on that date:

d = datetime.date(1970,1,1)
dtt = d.timetuple() # time.struct_time(tm_year=1970, tm_mon=1, tm_mday=1, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=1, tm_isdst=-1)
ts = time.mktime(dtt) # 28800.0

28800.0 is 8 hours, which would be correct for the Pacific time zone (where I'm at).

like image 43
DRH Avatar answered Oct 17 '22 15:10

DRH