Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python - Datetime not accounting for leap second properly?

I am parsing some data that has the leapsecond timestampe datetime 2012-06-30T23:59:60.209215. I used following code to parse that string and convert to a datetime object:

    nofrag, frag = t.split('.')
    nofrag_dt = datetime.datetime.strptime(nofrag, "%Y-%m-%dT%H:%M:%S")
    dt = nofrag_dt.replace(microsecond=int(frag))

Python documentation claims that this shouldn't be an issue as %S accepts [0, 61]. But, I get this error with the above timestamp

nofrag_dt = datetime.datetime.strptime(nofrag, "%Y-%m-%dT%H:%M:%S")
ValueError: second must be in 0..59

Thanks

like image 556
madtowneast Avatar asked Jan 09 '14 17:01

madtowneast


People also ask

Does Python datetime handle leap seconds?

Unlike the time module, the datetime module does not support leap seconds.

How do I convert datetime to seconds in Python?

To convert a datetime to seconds, subtracts the input datetime from the epoch time. For Python, the epoch time starts at 00:00:00 UTC on 1 January 1970. Subtraction gives you the timedelta object. Use the total_seconds() method of a timedelta object to get the number of seconds since the epoch.

How do I remove T and Z from timestamp in Python?

To remove timestamp, tzinfo has to be set None when calling replace() function.

What is datetime datetime now () in Python?

datetime. now() method contains the year, month, day, hour, minute, second, and microsecond (expressed as YYYY-MM-DD hh:mm:ss. ffffff ). It also accepts an optional time_zone parameter, which is set to None by default.


2 Answers

The documentation for %S says:

Unlike the time module, the datetime module does not support leap seconds.

The time string "2012-06-30T23:59:60.209215" implies that the time is in UTC (it is the last leap second at the moment):

import time
from calendar import timegm
from datetime import datetime, timedelta

time_string = '2012-06-30T23:59:60.209215'
time_string, dot, us = time_string.partition('.')
utc_time_tuple = time.strptime(time_string, "%Y-%m-%dT%H:%M:%S")
dt = datetime(1970, 1, 1) + timedelta(seconds=timegm(utc_time_tuple))
if dot:
    dt = dt.replace(microsecond=datetime.strptime(us, '%f').microsecond)
print(dt)
# -> 2012-07-01 00:00:00.209215
like image 87
jfs Avatar answered Oct 14 '22 01:10

jfs


Do this:

import time
import datetime 
t = '2012-06-30T23:59:60.209215'
nofrag, frag = t.split('.')
nofrag_dt = time.strptime(nofrag, "%Y-%m-%dT%H:%M:%S")
ts = datetime.datetime.fromtimestamp(time.mktime(nofrag_dt))
dt = ts.replace(microsecond=int(frag))
print(dt)

Output is:

2012-07-01 00:00:00.209215
like image 31
Velimir Mlaker Avatar answered Oct 13 '22 23:10

Velimir Mlaker