Python `fromtimestamp` performs discrete transition

I use datetime.fromtimestamp to convert an era time to local time. I found that datetime.fromtimestamp performs a one-hour discrete jump at a specific point in time, and I'm completely confused why it does it.

(I also use time.mktime to convert a datetime object to an era, as suggested by Raymond Hettinger . I'm not sure if this is relevant information for this question, so I’m just in case.)

 Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) [GCC 4.5.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import time, datetime >>> def datetime_to_epoch_time(datetime_): ... return time.mktime(datetime_.timetuple()) + datetime_.microsecond / 1e6 ... 

Selecting a specific time of an era:

 >>> x = datetime_to_epoch_time(datetime.datetime(2012, 3, 30, 3, 0)) 

Convert it to datetime using fromtimestamp :

 >>> datetime.datetime.fromtimestamp(x) datetime.datetime(2012, 3, 30, 3, 0) 

We get the time 3am.

Now let's convert the time that is exactly one second before it:

 >>> datetime.datetime.fromtimestamp(x-1) datetime.datetime(2012, 3, 30, 1, 59, 59) 

We suddenly get one to two in the morning!

What happened? I know that such things happen on days of a leap jump, but since when is March 30 a leap day?

I should note that this only happened to me on Linux, not on Windows. And I think that different Linux computers (in different time zones) have a different time point at which fromtimestamp makes the jump.

+6
source share
2 answers

Easy. March 30, apparently, is a daylight saving time transition in your time zone.

So, on this day, the time really lasted from 1:59:59 to 3:00:00

+4
source

fromtimestamp uses the current user "local environment" defined by the POSIX C library (see man (3) tzset and docs of the time module).

If you really want to get a pytz current local user environment locally, the datetime-tz package has a function for automatic detection.

However, the general wisdom is to always work with UTC and avoid all DST problems (use the local time zone only for final display). Use datetime.fromtimestamp(x, tz=pytz.UTC) , or if you don't have pytz :

 >>> datetime.datetime.fromtimestamp(x) datetime.datetime(2012, 3, 30, 3, 0) >>> datetime.datetime.utcfromtimestamp(x) datetime.datetime(2012, 3, 30, 0, 0) >>> datetime.datetime.utcfromtimestamp(x-1) datetime.datetime(2012, 3, 29, 23, 59, 59) 

PS You can also set the locale of your process in UTC (but this may not work on OSs other than POSIX):

 >>> import os,time >>> os.environ["TZ"] = "UTC" >>> time.tzset() >>> datetime.datetime.fromtimestamp(x) datetime.datetime(2012, 3, 30, 0, 0) 
+7
source

Source: https://habr.com/ru/post/911890/


All Articles