为任何架构获得尽可能高的 gmtime
Get the highest possible gmtime for any architecture
我遇到了一个问题,开始于 here。我发现了原因并且没有尝试解决其他问题。
我需要的是将 CherryPy 设置为在不同平台上可用的最长可能会话时间。为此 CherryPy 使用 time.gmtime()
。在我的 Windows 64 位上,我可以毫无问题地将会话超时设置为未来 100 年,但这在 armhf 平台上不起作用。 armhf 允许我将会话设置为 22 年。
不是 我正在寻找一种根据体系结构动态设置超时的方法。
在 armhf 上,我尝试使用 time.gmtime(sys.maxsize)
,它返回了 2038 年的日期。time.gmtime(sys.maxsize+1)
Returns OverflowError: timestamp out of range for platform time_t
错误。所以我想这是可能的最晚日期。
问题是在我的 Windows 64 位机器上做同样的事情(其中 sys.maxsize = 9223372036854775807
)time.gmtime(sys.maxsize)
returns OSError: [Errno 22] Invalid argument
。有没有办法在 architecture/platform 中执行此操作?
编辑: 这个问题不仅是由我在 CherryPy 中的代码引起的,其中会话的超时值对于某些 platforms/architectures(主要是 arm)来说太高了,但是在其中一些(Arm7)上,它也是由 CherryPy 内部引起的。
给定 python 版本的 time.gmtime 的最高可能值由编译此 python 的 time_t 类型的最高可能值决定。任何架构的最小理智 time_t python 是 运行 是 32 位有符号整数(Python 文档说最小 sys.maxint 是 2**31-1) .这意味着答案是 time.gmtime(2 ** 31 - 1) == time.gmtime(2147483647) == time.struct_time(tm_year=2038, tm_mon= 1、tm_mday=19,tm_hour=3,tm_min=14,tm_sec=7,tm_wday=1,tm_yday=19。 ..).
另见 https://en.wikipedia.org/wiki/Year_2038_problem
time.gmtime()
接受浮点数,因此其输入受限于 sys.float_info.max
或 int
in the range of C long
(or long long
if available).
要找到 "the highest date possible" 我们可以使用二进制搜索,如
@BlackJack's answer:
#!/usr/bin/env python
import ctypes
import sys
import time
MAX_TIME = max(int(sys.float_info.max),
2**(8*ctypes.sizeof(getattr(ctypes, 'c_longlong', ctypes.c_long))))
BOUNDARY = 0.5
assert False < BOUNDARY < True # necessary for the binary search to work
class GmtimeOverflowTable:
def __getitem__(self, timestamp):
assert timestamp >= 0
try:
time.gmtime(timestamp)
except (OSError, OverflowError, ValueError): # ValueError for Python <3.3
return True # overflow
return False
def find_max_gmtime_timestamp():
overflow = GmtimeOverflowTable()
assert overflow[float('+inf')] and not overflow[0]
if overflow[MAX_TIME]:
ts = binary_search(overflow, BOUNDARY, 0, MAX_TIME)
assert overflow[ts] and not overflow[ts - 1]
return ts - 1
raise OverflowError("Max gmtime timestamp is larger than " + str(MAX_TIME))
print(find_max_gmtime_timestamp())
其中 binary_search()
是一个自定义函数,用于接受超出 bisect.bisect()
范围的输入:
def binary_search(haystack, needle, lo, hi): # avoid bisect() range limitation
while lo < hi:
mid = (lo + hi) // 2
if haystack[mid] > needle:
hi = mid
elif haystack[mid] < needle:
lo = mid + 1
else:
return mid
return hi
我机器上的结果:
| Python version | max gmtime timestamp |
|----------------------+----------------------|
| Python 2.7.9 | 67768036191676795 |
| Python 3.4.3 | 67768036191676799 |
| Pypy (Python 2.7.9) | 67768036191676795 |
| Pypy3 (Python 3.2) | 67768036191676795 |
| Jython 2.7.0 | 9223372036854777 |
67768036191676799
Python 3 max gmtime()
时间戳对应max 32-bit int
year:
>>> import time; time.gmtime(67768036191676799)
time.struct_time(tm_year=2147485547, tm_mon=12, tm_mday=31, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=2, tm_yday=365, tm_isdst=0)
>>> 2147485547-1900
2147483647
>>> 2**31-1
2147483647
In general, Python time.gmtime()
delegates to the platform C gmtime()
function:
Most of the functions defined in this module call platform C library
functions with the same name. It may sometimes be helpful to consult
the platform documentation, because the semantics of these functions
varies among platforms.
The corresponding function signature in C11:
struct tm *gmtime(const time_t *timer);
time_t
limits are implementation-defined in C:
The range and precision of times representable in clock_t and time_t
are implementation-defined.
time_t
is required to be a real type on c11:
real types
integer types
char
sίgned integer types
standard sίgned integer types
signed char, short int, int, long int, long long int
extended sίgned integer types
unsίgned integer types
standard unsίgned integer types
_Bool, unsigned char, unsigned short int, unsigned int,
unsigned long int, unsigned long long int
extended unsίgned integer types
enumeration types
real floating types
float, double, long double
即原则上 time_t
可以是扩展整数类型或例如 long double。
time_t
is an integer type on POSIX
max time_t
可能大于 sys.maxsize
例如,time_t
在 32 位系统上可能是 64 位类型。
另请参阅:
- Maximum values for time_t (struct timespec)
- What is the biggest useful value of time_t?
可以在不知道 time_t
限制的情况下找到最大 gmtime()
时间戳:
def find_max_gmtime_timestamp():
ts = 1
overflow = GmtimeOverflowTable()
assert overflow[float('+inf')] and not overflow[ts]
while not overflow[ts]:
ts *= 2
ts = binary_search(overflow, BOUNDARY, ts//2, ts)
max_ts = ts - 1
assert overflow[max_ts+1] and not overflow[max_ts]
return max_ts
结果是一样的
如果 TZ=right/UTC
那么结果是 67768036191676825
对应于相同的最大时间 2147485547-12-31 23:59:59 UTC
。 right/UTC
时间戳较大,因为它包括闰秒(26
截至 2015-07-01
)。
我遇到了一个问题,开始于 here。我发现了原因并且没有尝试解决其他问题。
我需要的是将 CherryPy 设置为在不同平台上可用的最长可能会话时间。为此 CherryPy 使用 time.gmtime()
。在我的 Windows 64 位上,我可以毫无问题地将会话超时设置为未来 100 年,但这在 armhf 平台上不起作用。 armhf 允许我将会话设置为 22 年。
不是 我正在寻找一种根据体系结构动态设置超时的方法。
在 armhf 上,我尝试使用 time.gmtime(sys.maxsize)
,它返回了 2038 年的日期。time.gmtime(sys.maxsize+1)
Returns OverflowError: timestamp out of range for platform time_t
错误。所以我想这是可能的最晚日期。
问题是在我的 Windows 64 位机器上做同样的事情(其中 sys.maxsize = 9223372036854775807
)time.gmtime(sys.maxsize)
returns OSError: [Errno 22] Invalid argument
。有没有办法在 architecture/platform 中执行此操作?
编辑: 这个问题不仅是由我在 CherryPy 中的代码引起的,其中会话的超时值对于某些 platforms/architectures(主要是 arm)来说太高了,但是在其中一些(Arm7)上,它也是由 CherryPy 内部引起的。
给定 python 版本的 time.gmtime 的最高可能值由编译此 python 的 time_t 类型的最高可能值决定。任何架构的最小理智 time_t python 是 运行 是 32 位有符号整数(Python 文档说最小 sys.maxint 是 2**31-1) .这意味着答案是 time.gmtime(2 ** 31 - 1) == time.gmtime(2147483647) == time.struct_time(tm_year=2038, tm_mon= 1、tm_mday=19,tm_hour=3,tm_min=14,tm_sec=7,tm_wday=1,tm_yday=19。 ..). 另见 https://en.wikipedia.org/wiki/Year_2038_problem
time.gmtime()
接受浮点数,因此其输入受限于 sys.float_info.max
或 int
in the range of C long
(or long long
if available).
要找到 "the highest date possible" 我们可以使用二进制搜索,如 @BlackJack's answer:
#!/usr/bin/env python
import ctypes
import sys
import time
MAX_TIME = max(int(sys.float_info.max),
2**(8*ctypes.sizeof(getattr(ctypes, 'c_longlong', ctypes.c_long))))
BOUNDARY = 0.5
assert False < BOUNDARY < True # necessary for the binary search to work
class GmtimeOverflowTable:
def __getitem__(self, timestamp):
assert timestamp >= 0
try:
time.gmtime(timestamp)
except (OSError, OverflowError, ValueError): # ValueError for Python <3.3
return True # overflow
return False
def find_max_gmtime_timestamp():
overflow = GmtimeOverflowTable()
assert overflow[float('+inf')] and not overflow[0]
if overflow[MAX_TIME]:
ts = binary_search(overflow, BOUNDARY, 0, MAX_TIME)
assert overflow[ts] and not overflow[ts - 1]
return ts - 1
raise OverflowError("Max gmtime timestamp is larger than " + str(MAX_TIME))
print(find_max_gmtime_timestamp())
其中 binary_search()
是一个自定义函数,用于接受超出 bisect.bisect()
范围的输入:
def binary_search(haystack, needle, lo, hi): # avoid bisect() range limitation
while lo < hi:
mid = (lo + hi) // 2
if haystack[mid] > needle:
hi = mid
elif haystack[mid] < needle:
lo = mid + 1
else:
return mid
return hi
我机器上的结果:
| Python version | max gmtime timestamp |
|----------------------+----------------------|
| Python 2.7.9 | 67768036191676795 |
| Python 3.4.3 | 67768036191676799 |
| Pypy (Python 2.7.9) | 67768036191676795 |
| Pypy3 (Python 3.2) | 67768036191676795 |
| Jython 2.7.0 | 9223372036854777 |
67768036191676799
Python 3 max gmtime()
时间戳对应max 32-bit int
year:
>>> import time; time.gmtime(67768036191676799)
time.struct_time(tm_year=2147485547, tm_mon=12, tm_mday=31, tm_hour=23, tm_min=59, tm_sec=59, tm_wday=2, tm_yday=365, tm_isdst=0)
>>> 2147485547-1900
2147483647
>>> 2**31-1
2147483647
In general, Python time.gmtime()
delegates to the platform C gmtime()
function:
Most of the functions defined in this module call platform C library functions with the same name. It may sometimes be helpful to consult the platform documentation, because the semantics of these functions varies among platforms.
The corresponding function signature in C11:
struct tm *gmtime(const time_t *timer);
time_t
limits are implementation-defined in C:
The range and precision of times representable in clock_t and time_t are implementation-defined.
time_t
is required to be a real type on c11:
real types
integer types
char
sίgned integer types
standard sίgned integer types
signed char, short int, int, long int, long long int
extended sίgned integer types
unsίgned integer types
standard unsίgned integer types
_Bool, unsigned char, unsigned short int, unsigned int,
unsigned long int, unsigned long long int
extended unsίgned integer types
enumeration types
real floating types
float, double, long double
即原则上 time_t
可以是扩展整数类型或例如 long double。
time_t
is an integer type on POSIX
max time_t
可能大于 sys.maxsize
例如,time_t
在 32 位系统上可能是 64 位类型。
另请参阅:
- Maximum values for time_t (struct timespec)
- What is the biggest useful value of time_t?
可以在不知道 time_t
限制的情况下找到最大 gmtime()
时间戳:
def find_max_gmtime_timestamp():
ts = 1
overflow = GmtimeOverflowTable()
assert overflow[float('+inf')] and not overflow[ts]
while not overflow[ts]:
ts *= 2
ts = binary_search(overflow, BOUNDARY, ts//2, ts)
max_ts = ts - 1
assert overflow[max_ts+1] and not overflow[max_ts]
return max_ts
结果是一样的
如果 TZ=right/UTC
那么结果是 67768036191676825
对应于相同的最大时间 2147485547-12-31 23:59:59 UTC
。 right/UTC
时间戳较大,因为它包括闰秒(26
截至 2015-07-01
)。