12

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

4

2 Answers 2

8

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
5
  • How does it imply that the time is in UTC? I see no trailing Z or +00:00. Sep 6, 2014 at 0:05
  • @MattJohnson: look up the time of the last leap second (it is the same time moment around the world).
    – jfs
    Sep 6, 2014 at 0:06
  • Ah! Very nice! You got me there! :) Sep 6, 2014 at 0:07
  • time_string.rpartition('.') should be time_string.partition('.'), since if there is no dot then the former makes time_string the empty string and ms gets the non-trivial value.
    – unutbu
    Mar 10, 2015 at 1:36
  • @unutbu: thank you. I don't know why I've used .rpartition() here.
    – jfs
    Mar 10, 2015 at 2:18
1

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
1
  • note: the round trip through the local time may fail (e.g., during DST transitions) and it is unnecessary as my answer demonstrates.
    – jfs
    Mar 10, 2015 at 2:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.