日期时间接近纪元的Windows在Windows上崩溃 [英] Python crash on Windows with a datetime close to the epoch

查看:67
本文介绍了日期时间接近纪元的Windows在Windows上崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Windows 10上的Python 3.7:

 >>从datetime导入datetime 
>> datetime.fromtimestamp(0)
datetime.datetime(1970,1,1,0,0)
>> datetime.fromtimestamp(0).timestamp()
追溯(最近一次调用为最新):
文件< stdin>,< module>中的第1行。
OSError:[错误22]无效的参数
>>> datetime.fromtimestamp(3600 * 3).timestamp()
追溯(最近一次调用为最后一次):
文件< stdin>,< module>中的第1行。
OSError:[错误22]无效的参数
>>> datetime.fromtimestamp(360000).timestamp()
360000.0

我了解在Windows上,由于32位整数大小,时间戳的范围限制为1970 – 2038。但确实令人奇怪的是,它崩溃在应该仍然允许的时间戳上。 FWIW,我使用的是UTC + 2,所以如果时区存在问题,我希望 3600 * 3 (3小时)时间戳起作用。我可以以某种方式进行这项工作,还是应该接受非常低的时间戳不起作用?

解决方案

好吧,我做了一些深入研究Python的源代码。问题出在函数 _PyTime_localtime 中。这会调用 localtime_s 函数接受2个参数 time_t t struct tm * tm 。其中 t 是要转换的 time_t 对象,而 tm 是结果时间结构。当您将0作为 time_t 传递时(这是完全有效的),结果结构将字段 tm_hour 设置为1机。另外,还有用于非Windows变体的其他代码,它们代替地调用 localtime_r 。 / p>

现在,问题转移到内部使用的函数 utc_to_seconds 中,该函数采用时间结构(分成类似这样的参数) : int年,整数月,整数日,整数小时,整数分钟,整数秒)。现在对于年,月和日都没有问题,它将转换为序数(这是正确的序数顺便说一句)。但是函数的最后一行如下:

  return((常规* 24 +小时)* 60 +分钟)* 60 +秒; 

EPOCH应该在那里返回62135683200,但是由于这个额外的小时,我们得到了62135686800。

这一切都在内部函数 local_to_seconds

中在一起

  long long t,a,b,u1,u2,t1,t2,lt; 
t = utc_to_seconds(年,月,日,小时,分钟,秒);
/ *我们的目标是解决u的t = local(u)。 * /
lt = local(t);
如果(lt == -1)
返回-1;
a = lt-t;
u1 = t-a;
t1 = local(u1);

其中 t = 62135683200 lt = 62135686800 。我们以 u1 = -3600 结束,这将导致参数无效。



因此可以得出结论:问题是当您调用时间戳时。我不确定要用C代码修复的解决方案是什么,但是我猜它肯定看起来像是个错误。


Python 3.7 on Windows 10:

>>> from datetime import datetime
>>> datetime.fromtimestamp(0)
datetime.datetime(1970, 1, 1, 0, 0)
>>> datetime.fromtimestamp(0).timestamp()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
>>> datetime.fromtimestamp(3600 * 3).timestamp()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OSError: [Errno 22] Invalid argument
>>> datetime.fromtimestamp(360000).timestamp()
360000.0

I understand that on Windows, the range for timestamps is limited to 1970 – 2038 due to 32-bit integer size. But it's really strange that it crashes on a timestamp that should still be allowed. FWIW, I am in UTC+2, so if there is some issue with the timezone, I expected the 3600 * 3 (3 hour) timestamp to work. Can I make this work somehow or should I just accept that very low timestamps are not going to work?

解决方案

Ok I did some digging in the source code of the Python. The problem lies within the function _PyTime_localtime. This calls the localtime_s function takes 2 arguments time_t t and struct tm *tm. Where t is a time_t object to convert and tm the resulting time structure. When you pass 0 as time_t, which is perfectly valid, the resulting structure has the field tm_hour set to 1 on my machine. Also there is other code for Non-Windows variants, which calls localtime_r in stead.

Now the problem gets moved to the internally used function utc_to_seconds, which takes the time structure (split into arguments like so: int year, int month, int day, int hour, int minute, int second). Now for the year, month and day there is no problem, it gets converted to an ordinal (which is the correct ordinal btw). But then the function has the following last line:

return ((ordinal * 24 + hour) * 60 + minute) * 60 + second;

Where EPOCH is supposed to return 62135683200 there, but due to this extra hour we get 62135686800.

This all comes together in the internal function local_to_seconds

long long t, a, b, u1, u2, t1, t2, lt;
t = utc_to_seconds(year, month, day, hour, minute, second);
/* Our goal is to solve t = local(u) for u. */
lt = local(t);
if (lt == -1)
    return -1;
a = lt - t;
u1 = t - a;
t1 = local(u1);

Where t = 62135683200 and lt = 62135686800. We end up with u1 = -3600 which results in the invalid parameter.

So to conclude: The problem is when you call timestamp. I'm not exactly sure what the solution would be to fix it in the C-code, but it definitely looks like a bug I guess.

这篇关于日期时间接近纪元的Windows在Windows上崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆