python 2.7 mktime给出了相同输入的不同值

时间:2016-05-20 02:39:48

标签: python linux datetime

以下代码在Windows上运行良好,Linux [Ubuntu]中的结果很奇怪。 我的python版本是2.7

from datetime import datetime
from datetime import timedelta
import time

def time_diff(date_str_1, date_str_2):
    time_stamp_1 = time.mktime(time.strptime(date_str_1, '%Y-%m-%d-%H-%M-%S'))
    time_stamp_2 = time.mktime(time.strptime(date_str_2, '%Y-%m-%d-%H-%M-%S'))
    print '==='
    print date_str_1,date_str_2
    print time_stamp_1,time_stamp_2
    delta1 = time_stamp_2 - time_stamp_1
    return delta1

print time_diff('2015-11-01-01-00-00', '2015-11-01-01-30-00')
print time_diff('2015-11-01-01-00-00', '2015-11-01-02-00-00')
print time_diff('2015-11-01-01-00-00', '2015-11-01-02-30-00')
print time_diff('2015-11-01-01-00-00', '2015-11-01-03-00-00')

导致Windows

===
2015-11-01-01-00-00 2015-11-01-01-30-00
1446310800.0 1446312600.0
1800.0
===
2015-11-01-01-00-00 2015-11-01-02-00-00
1446310800.0 1446314400.0
3600.0
===
2015-11-01-01-00-00 2015-11-01-02-30-00
1446310800.0 1446316200.0
5400.0
===
2015-11-01-01-00-00 2015-11-01-03-00-00
1446310800.0 1446318000.0
7200.0

导致Linux

===
2015-11-01-01-00-00 2015-11-01-01-30-00
1446364800.0 1446366600.0
1800.0
===
2015-11-01-01-00-00 2015-11-01-02-00-00
1446364800.0 1446372000.0
7200.0
===
2015-11-01-01-00-00 2015-11-01-02-30-00
1446368400.0 1446373800.0
5400.0
===
2015-11-01-01-00-00 2015-11-01-03-00-00
1446368400.0 1446375600.0
7200.0
Linux上的

' 2015-11-01-01-00-00'有时是1446364800.0然后它变成1446368400.0

原因是什么?这是一个错误吗?

4 个答案:

答案 0 :(得分:0)

我想这个故障是在你的linux系统中。我运行了一个类似BSD unix的macOS,也运行在pythonanywhere,一个linux服务器上,两者都得到了与Windows完全相同的结果。

===
2015-11-01-01-00-00 2015-11-01-01-30-00
1446339600.0 1446341400.0
1800.0
===
2015-11-01-01-00-00 2015-11-01-02-00-00
1446339600.0 1446343200.0
3600.0
===
2015-11-01-01-00-00 2015-11-01-02-30-00
1446339600.0 1446345000.0
5400.0
===
2015-11-01-01-00-00 2015-11-01-03-00-00
1446339600.0 1446346800.0
7200.0

我建议您检查所有区域设置配置,以便更改datetime之类的内容。您可以在bash中输入locale来检查。我的两个环节都有LC_CTYPE="UTF-8"。其他人可能是"C"POSIX

LANG=
LC_COLLATE="C"
LC_CTYPE="UTF-8"
LC_MESSAGES="C"
LC_MONETARY="C"
LC_NUMERIC="C"
LC_TIME="C"
LC_ALL=

答案 1 :(得分:0)

time.mktime()返回自1970.01.01 00:00:00以来添加OS时区的秒数。如果值已更改,则可能是您的操作系统时区已更改。

deepin@deepin-pc:~/test$ python testtime.py 
===
2015-11-01-01-00-00 2015-11-01-01-30-00
1446310800.0 1446312600.0
1800.0
===
2015-11-01-01-00-00 2015-11-01-02-00-00
1446310800.0 1446314400.0
3600.0
===
2015-11-01-01-00-00 2015-11-01-02-30-00
1446310800.0 1446316200.0
5400.0
===
2015-11-01-01-00-00 2015-11-01-03-00-00
1446310800.0 1446318000.0
7200.0
deepin@deepin-pc:~/test$ date -R
Fri, 20 May 2016 11:26:43 +0800
deepin@deepin-pc:~/test$ python testtime.py 
===
2015-11-01-01-00-00 2015-11-01-01-30-00
1446373800.0 1446375600.0
1800.0
===
2015-11-01-01-00-00 2015-11-01-02-00-00
1446373800.0 1446377400.0
3600.0
===
2015-11-01-01-00-00 2015-11-01-02-30-00
1446373800.0 1446379200.0
5400.0
===
2015-11-01-01-00-00 2015-11-01-03-00-00
1446373800.0 1446381000.0
7200.0
deepin@deepin-pc:~/test$ date -R
Thu, 19 May 2016 17:56:59 -0930
deepin@deepin-pc:~/test$

答案 2 :(得分:0)

1446364800.01446368400.0都是'2015-11-01 01:00:00'输入的有效时间戳(在America/Los_Angeles时区中):

>>> from datetime import datetime
>>> import pytz     # $ pip install pytz
>>> import tzlocal  # $ pip install tzlocal
>>> tz = tzlocal.get_localzone()
>>> epoch = datetime(1970, 1, 1, tzinfo=pytz.utc)
>>> (tz.localize(datetime(2015, 11, 1, 1), is_dst=True) - epoch).total_seconds()
1446364800.0
>>> (tz.localize(datetime(2015, 11, 1, 1), is_dst=False) - epoch).total_seconds()
1446368400.0

time.mktime()是相应C mktime()函数的瘦包装器。 mktime()可以访问Linux上的tz数据库,因此它会尝试在那里找到正确的utc偏移量。如果时间不明确,那么结果可能取决于mktime()来电的历史记录:

>>> import time
>>> time.mktime((2015, 11, 1, 1, 0, 0, -1, -1, -1)) # ambiguous time in Los Angeles
1446364800.0                                        # random value
>>> time.mktime((2015, 11, 1, 3, 0, 0, -1, -1, -1)) # unambiguous
1446375600.0                                        # EST time
>>> time.mktime((2015, 11, 1, 1, 0, 0, -1, -1, -1)) # EST utc offset is chosen
1446368400.0
>>> time.mktime((2015, 11, 1, 0, 0, 0, -1, -1, -1)) # unambiguous
1446361200.0                                        # EDT time
>>> time.mktime((2015, 11, 1, 1, 0, 0, -1, -1, -1)) # EDT utc offset is chosen
1446364800.0

在这种情况下,如果输入不明确,mktime()默认为最后一个utc偏移量(在我的机器上)。

Windows无法提供对the tz databasepython进程的访问权限,因此mktime()可能会使用当前(可能不正确的过去日期)utc偏移。

请参阅python converting string in localtime to UTC epoch timestamp

答案 3 :(得分:0)

看起来像DST问题......

大多数日期只有舍入错误,除了 ...

2015-11-01-01-00-00 2015-11-01-02-00-00

windows提供3600.0 vs linux 7200.0。那是完全一小时的差异。

您选择的这两个日期恰好是从夏令时回到2015年标准时间的过渡时间。

因此,所有其他因素相同(例如,时区设置正确)可能是影响其处理方式的一个因素。是否在DST转换之前或之后考虑日期。

也就是说mktime是否认为你有一个以DST表示的日期。这可能因libc mktime实现而异。

前一段时间我的perl代码需要[更好] mktime实现,所以我查看了mktime vs {(例如netBSD)中的glibc来源,它们肯定是不同的关于他们如何做事。

我查看了*BSDandroidminux和IIRC上的一些实现,它们都与netBSD版本相似/相同。不知道,自从我这么做以后已经有一段时间了。但是,glibc版本看起来像是从头开始编写的,而不是从其他任何版本派生的。

显然,我不知道Window的版本,但如果他们想借用一些代码,他们可能会借用BSD式的实现,部分是为了获得许可,但也因为他们可能在linux出现之前借用了代码。再一次,不知道。

2015年的夏令时转型是:

03/08/2015 02:00:00 [Sun] --> 03/08/2015 03:00:00 [Sun] (spring forward)
11/01/2015 01:00:00 [Sun] <-- 11/01/2015 02:00:00 [Sun] (fall back)