Converting datetime object to timestamp and back gives me a different time - python

I have encountered this problem today and I don't have an explanation for it.
I have a Python datetime object:
dt = datetime.datetime(2012, 3, 31, 18, 30, 48, tzinfo=<FixedOffset '-04:00'>)
which, to my understanding is 18:30 in a time zone offset from UTC by 4 hours.
I then tried to convert it to timestamp like so:
epo = time.mktime(dt.timetuple()) and get back 1333247448.0.
However, when I try to convert it back to make sure it's correct using date
time.datetime.fromtimestring(epo),
I get back
datetime.datetime(2012, 3, 31, 19, 30, 48)
Notice that time is 19 not 18.
Can anybody tell me why it's doing that?

Try using
time.localtime(epo)
instead of
time.datetime.fromtimestring(epo)

Related

Difference between datetime.strptime and parse from dateutil?

I am getting two different results in seconds when I parse the following time string:
Method 1:
from datetime import datetime
int(datetime.strptime('2015-03-25T19:46:23.286966Z', '%Y-%m-%dT%H:%M:%S.%fZ').timestamp())
yields 1427309183
Method 2:
from dateutil.parser import parse
int(parse('2015-03-25T19:46:23.286966Z').timestamp())
yields 1427312783
It seems that method 1 ignores the TZ vs method do (I run it from a UTC+1 tz).
Question: Why do these two methods yield different second timestamps? Can someone please explain what's going on under the hood and how to best handle such situations.
My goal is to convert the string to seconds in unix epoch time (i.e. utc).
If you take a look at the repr of your intermediate result (the datetime objects), you notice a difference:
from datetime import datetime
from dateutil.parser import parse
print(repr(datetime.strptime('2015-03-25T19:46:23.286966Z', '%Y-%m-%dT%H:%M:%S.%fZ')))
# datetime.datetime(2015, 3, 25, 19, 46, 23, 286966)
print(repr(parse('2015-03-25T19:46:23.286966Z')))
# datetime.datetime(2015, 3, 25, 19, 46, 23, 286966, tzinfo=tzutc())
The first one is naive, no tzinfo set since you use a literal Z in the parsing directive. The second one is aware; tzinfo is set to UTC since dateutil's parser recognizes the Z to signal UTC. That makes for the difference in the timestamp, since Python treats naive datetime as local time - thus the difference of 1 hour, which is your local time's UTC offset.
You can correctly parse like
print(repr(datetime.fromisoformat('2015-03-25T19:46:23.286966Z'.replace('Z', '+00:00'))))
# datetime.datetime(2015, 3, 25, 19, 46, 23, 286966, tzinfo=datetime.timezone.utc)
see also here.
Or less convenient (imho), with strptime:
print(repr(datetime.strptime('2015-03-25T19:46:23.286966Z', '%Y-%m-%dT%H:%M:%S.%f%z')))
# datetime.datetime(2015, 3, 25, 19, 46, 23, 286966, tzinfo=datetime.timezone.utc)

Python3.5 Time Zone conversion

I have tried a number of posts/suggestions on here on converting time zone objects and have failed. I hope someone can point me to an easy way to do this.
I have a string/datetime of 2017-05-11T16:24:56-04:00
I can parse it a number of ways, dateutil, etc, into a datetime object.
when printed i get
datetime.datetime(2017, 5, 11, 16, 24, 56, tzinfo=tzoffset(None, -14400))
so it gets a tzoffset.
Trying any conversion doesn't seem to update the actual time portion, just the zone information.
How do I convert this string to my local time zone (EST, or offset -5hrs).
edit: trying astimezone() gets me this:
dt.astimezone()
Out[18]: datetime.datetime(2017, 5, 11, 16, 24, 56,
tzinfo=datetime.timezone(datetime.timedelta(-1, 72000), 'EDT'))
Thanks!
When you convert it using tzinfo you only change the suffix of the output string (e.g. with tzutc()): 2017-05-11 16:24:56+00:00
If you want to print it in your time zone, first create the datetime object using the actual timezone it represents:
dt = datetime(2017, 5, 11, 16, 24, 56,
tzinfo=tzoffset(None, -18000))
# 2017-05-11 16:24:56-05:00
And then convert it to the desired timezone using:
mydt = dt.astimezone(tzutc())
# 2017-05-11 21:24:56+00:00

How to convert a timestamp string with 7 digits on the microseconds part using strptime?

Having a timestamp as string like 2016-09-22T13:57:31.2311892-04:00, how can one get the datetime object?
I've tried using strptime for this, but I got two issues:
I need to remove : from the timezone part, at the end, for %z to work properly.
The microseconds part has 7 digits, but strptime handles only up to 6 digits.
Is there a way to parse timestamps in this format without modifying* the string itself before passing to strptime?
* - by modifying, I think of removing the last microsecond digit, and removing the last :.
Note: This is for inserting a record in MySQL. If that helps.
How about convert like this:
dt = datetime.strptime(s[:-len('2-04:00')], '%Y-%m-%dT%H:%M:%S.%f')
# datetime.datetime(2016, 9, 22, 13, 57, 31, 231189)
https://docs.python.org/3/library/datetime.html#strftime-strptime-behavior
Suddenly found a useful method at django:
from django.utils.dateparse import parse_datetime
dt = parse_datetime('2016-09-22T13:57:31.2311892-04:00')
# datetime.datetime(2016, 9, 22, 13, 57, 31, 231189, tzinfo=<django.utils.timezone.FixedOffset object at 0x7f20184f8390>)
https://docs.djangoproject.com/en/2.0/ref/utils/#module-django.utils.dateparse
Another pythonic format (use maya https://github.com/kennethreitz/maya):
# pip install maya
import maya
maya.parse('2016-09-22T13:57:31.2311892-04:00').datetime()
# datetime.datetime(2016, 9, 22, 17, 57, 31, 231189, tzinfo=<UTC>)

getting wrong time delta in python

I am subtracting two dates in python 2.7 and getting wrong result in seconds. Apparently difference between these dates is more than 24h which is 86400s. But I am getting 44705s, why is that and how to fix it ?
>>> date1
datetime.datetime(2017, 10, 22, 11, 41, 28)
>>> date2
datetime.datetime(2017, 10, 20, 23, 16, 23)
>>> (date1-date2).seconds
44705
Calling .seconds will only give you the seconds component of the timedelta object, which only takes into account seconds, minutes, and hours (see docs for more detail). If you want the entire timedelta in seconds, call total_seconds.
>>> (date1 - date2).total_seconds()
131105.0
date1-date2 is datetime.timedelta(1, 44705). You're only looking at the seconds portion. Look at the days portion too.

Correctly parse date string with timezone information

I'm receiving a formatted date string like this via the pivotal tracker API: "2012/06/05 17:42:29 CEST"
I want to convert this string to a UTC datetime object, it looks like python-dateutil does not recognize that timezone, pytz doesn't know it either.
I fear my best bet is to replace CEST in the string with CET, but this feels very wrong. Is there any other way to parse summer time strings to UTC datetime objects I couldn't find?
pytz.timezone('CEST')
# -> pytz.exceptions.UnknownTimeZoneError: 'CEST'
dateutil.parser.parse("2012/06/05 17:42:29 CEST")
# -> datetime.datetime(2012, 6, 5, 17, 42, 29)
Edit: After thinking about it again subtracting one hour is completely false as the corresponding timezone is also currently in summer time, the issue of parsing still stands
There is no real CEST timezone. Use Europe/Paris, Europe/Berlin or Europe/Prague (or another one) according to your region:
>>> pytz.country_timezones('de')
[u'Europe/Berlin']
>>> pytz.country_timezones('fr')
[u'Europe/Paris']
They are (currently) identical and all referring to CEST in summer.
>>> dateutil.parser.parse("2012/06/05 17:42:29 CEST").astimezone(pytz.utc)
datetime.datetime(2012, 6, 5, 15, 42, 29, tzinfo=<UTC>)

Categories

Resources