Tampa
Tampa

Reputation: 78362

python will not convert date string to datetime

Here is my datetime format in python 2.7:

dt = "2018-12-28T21:59:59.434645118Z"
now_utc = datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S.%fZ")

Error:

ValueError: time data '2018-12-28T21:59:59.434645118Z' does not match format '%Y-%m-%dT%H:%M:%S.%fZ'

I have the microsecond with %f.. what else am I missing?

Thanks

Upvotes: 4

Views: 136

Answers (3)

Jason Baumgartner
Jason Baumgartner

Reputation: 301

The problem you are running into is that your time is in nanoseconds and the Python datetime module currently does not have nanosecond capability. It is proposed for the future, however.

Your best option is to reduce the resolution of the time to microseconds if your application allows for that.

Here's how you can fix this:

dt = "2018-12-28T21:59:59.434645118Z"
p1,p2 = dt.rsplit('.',1)
new_dt = "{}.{}Z".format(p1,p2[:-1][:6])
now_utc = datetime.datetime.strptime(new_dt, "%Y-%m-%dT%H:%M:%S.%fZ")

p1 represents '2018-12-28T21:59:59'

p2 represents the float part of seconds that is too large for datetime (it's nano precision) -- so we restrict it to 6 digits ([:-1] removes the Z and [:6] restricts to microseconds only). This reduces resolution to microseconds with no rounding -- it just truncates. If you need to round, you can cast p2 to a float, round it, then cast back to str and truncate the ending.

This will reduce the resolution of your time to something datetime can handle. This also assumes that your seconds are always a float and will end in point something. If not, you may need to tweak the regex but I tried to make the example as clear as possible.

I'm sure there is a simpler way to do this but this popped into my head first and it's late here. I was thinking about manipulating the dt string directly but I wasn't sure if 9 digits would always be in the decimal portion. Good luck!

Upvotes: 3

Bitto
Bitto

Reputation: 8245

The microsecond range allowed is

0 <= microsecond < 1000000

You can read more about it here https://docs.python.org/2/library/datetime.html#datetime-objects

If an argument outside those ranges is given, ValueError is raised. If you remove the last 3 characters of the microsecond ( ie. 118) it should work fine.

import datetime
dt = "2018-12-28T21:59:59.434645Z"
now_utc = datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S.%fZ")
print(now_utc)

One solution would be to keep take the microsecond substring so that it remains below the max value. I'm sure there are other ways to do this. this is just what i can think of now.

import datetime
max=1000000
dt = "2018-12-28T21:59:59.434645118Z"
dt_list=dt.split('.')
current_micro_sec=dt_list[1][:-1]
while int(current_micro_sec)>max:
    current_micro_sec=current_micro_sec[:-1]
    dt=dt_list[0]+'.'+current_micro_sec+'Z' #keep this inside only if > max otherwise preserve dt
now_utc = datetime.datetime.strptime(dt, "%Y-%m-%dT%H:%M:%S.%fZ")
print(now_utc)

Upvotes: 0

Usman
Usman

Reputation: 2029

Try this

from time import gmtime, strftime
import time

print(strftime("%Y-%m-%dT%H:%M:%S.%fZ", gmtime()))

Upvotes: 0

Related Questions