2

I know these questions have been asked before but I'm struggling to convert a timestamp string to a unix time and figuring out whether the datetime objects are naive or aware

For example, to convert the time "2021-05-19 12:51:47" to unix:

>>> from datetime import datetime as dt
>>> dt_obj = dt.strptime("2021-05-19 12:51:47", "%Y-%m-%d %H:%M:%S")
>>> dt_obj
datetime.datetime(2021, 5, 19, 12, 51, 47)

is dt_obj naive or aware and how would you determine this? The methods on dt_obj such as timetz, tzinfo, and tzname don't seem to indicate anything - does that mean that dt_obj is naive?

Then to get unix:

>>> dt_obj.timestamp()
1621421507.0

However when I check 1621421507.0 on say https://www.unixtimestamp.com then it tells me that gmt for the above is Wed May 19 2021 10:51:47 GMT+0000, ie 2 hours behind the original timestamp?

uroboros
  • 154
  • 7

3 Answers3

2

since Python's datetime treats naive datetime as local time by default, you need to set the time zone (tzinfo attribute):

from datetime import datetime, timezone

# assuming "2021-05-19 12:51:47" represents UTC:
dt_obj = datetime.fromisoformat("2021-05-19 12:51:47").replace(tzinfo=timezone.utc)

Or, as @Wolf suggested, instead of setting the tzinfo attribute explicitly, you can also modify the input string by adding "+00:00" which is parsed to UTC;

dt_obj = datetime.fromisoformat("2021-05-19 12:51:47" + "+00:00")

In any case, the result

dt_obj.timestamp()
# 1621428707.0

now converts as expected on https://www.unixtimestamp.com/: enter image description here

FObersteiner
  • 22,500
  • 8
  • 42
  • 72
  • 1
    What speaks against `datetime.fromisoformat("2021-05-19 12:51:47 +00:00")`? – Wolf May 25 '21 at 10:37
  • Thank you so much and noted on `datetime.fromisoformat` – uroboros May 25 '21 at 10:39
  • 1
    @Wolf: I've added your suggestion to the answer, thanks for the comment! I was a bit reluctant to the string modification but it's clearly more efficient than using `replace`. – FObersteiner May 25 '21 at 10:54
  • @MrFuppes Well, it adds to the input (`input+' +00:00'`), but doesn't your first solution modify the datetime object? Isn't this biased within one hour in a year, specifically between `2021-10-31 02:00:00 +02:00` and `2021-10-31 02:00:00 +01:00`? – Wolf May 25 '21 at 10:54
  • 1
    @uroboros: glad I could help! also take note of Wolf's suggestion; it's more efficient if you have a lot of data to process. – FObersteiner May 25 '21 at 10:55
  • 1
    @Wolf regarding *"Isn't this biased within one hour in a year"*: you mean because of a DST transition? - No I don't think so, assuming the input string represents UTC. If it would represent local time, then yes. You'd have to set the local time zone first and *then* convert to UTC (and then take timestamp if needed). – FObersteiner May 25 '21 at 10:58
2

As long as you don't specify the timezone when calling strptime, you will produce naive datetime objects. You may pass time zone information via %z format specifier and +00:00 added to the textual date-time representation to get a timezone aware datetime object:

from datetime import datetime

dt_str = "2021-05-19 12:51:47"
print(dt_str)
dt_obj = datetime.strptime(dt_str+"+00:00", "%Y-%m-%d %H:%M:%S%z")
print(dt_obj)
print(dt_obj.timestamp())

The of above script is this:

2021-05-19 12:51:47
2021-05-19 12:51:47+00:00
1621428707.0
Wolf
  • 9,679
  • 7
  • 62
  • 108
0

datetime.timestamp()

Naive datetime instances are assumed to represent local time and this method relies on the platform C mktime() function to perform the conversion.

So using this does automatically apply yours machine current timezone, following recipe is given to calculate timestamp from naive datetime without influence of timezone:

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
Daweo
  • 31,313
  • 3
  • 12
  • 25
  • although this is also suggested elsewhere, I think it is hard to read and only works because `datetime(1970, 1, 1)` is also treated as local time. To me, this seems like "right for the wrong reason". – FObersteiner May 25 '21 at 10:31