在 Python 中测量短间隔的最安全和最可靠的方法? (跨平台、跨硬件、抗夏令时和闰秒)
Safest and most reliable way to measure short intervals in Python? (cross-platform, cross-hardware, resistant to DST and leap seconds)
我对日期时间算法了解得越多,我就越头疼。
时间有很多种:
- 民用时间
- UTC
- 泰
- UNIX 时间
- 系统时间
- 线程时间
- CPU 时间
然后由于
时钟可以运行更快或更慢或者向后或向前跳跃
- 夏令时
- 跨越时区
- 闰秒
- NTP 同步
- 广义相对论
如何处理这些又取决于:
- 操作系统
- 硬件
- 编程语言
所以有人可以告诉我,对于我的具体用例,最安全和最可靠的测量短间隔的方法吗?这是我正在做的事情:
我正在 Python (3.7.x) 中制作 游戏,我需要跟踪自某些事件以来已经过了多长时间。例如,玩家按住按钮多长时间,或者敌人发现玩家多长时间,或者关卡加载多长时间。时间尺度应该精确到毫秒(纳秒是多余的)。
以下是我想确保避免的情况:
你在深夜玩游戏。在你所在的时区,那天晚上,夏令时凌晨 2 点时钟拨快一小时,所以分钟数为:1:58、1:59、2:00、3:01、3:02。游戏中每个与时间相关的变量突然都增加了一个小时——它认为你已经按住那个按钮 1 小时 2 秒,而不是仅仅 2 秒。灾难接踵而至。
相同,但 IERS 决定在当天的某个时间插入或减去闰秒。您玩转场,所有时间变量都会增加或减少一秒。灾难接踵而至。
你在火车或飞机上玩游戏,当你跨越时区边界 and/or 国际日期变更线时,灾难接踵而至。
在上述情况下,游戏在某些硬件和操作系统上可以正常运行,但在其他情况下则不能。 IE。它在 Linux 而不是 Window 时中断,反之亦然。
而且我真的不能为这些编写测试,因为有问题的事件很少发生。我需要在第一时间把它做好。那么,我需要使用什么时间相关的功能呢?我知道有普通的旧 time.time()
,但也有令人眼花缭乱的其他选项,例如
time.clock()
time.perf_counter()
time.process_time()
time.monotonic()
- 然后是上述所有的纳秒变体。
通过阅读文档,似乎 time.monotonic()
就是我想要的。但是,如果阅读有关计时的所有细节教会了我什么的话,那就是这些东西从来都不像它们看起来的那样。曾几何时,我以为我知道 "second" 是什么。现在我不太确定了。
那么,如何确保我的游戏时钟正常工作?
specification of time module 是查找每一项详细信息的最佳位置。
在那里,你可以很容易地看到:
time.clock()
已弃用,应替换为其他函数
time.process_time()
仅计算您的进程花费的 CPU 时间,因此它不适合测量挂钟时间(这是您需要的)
time.perf_counter()
和time.process_time()
有同样的问题
time.time()
刚刚好,但如果用户修改当前时间,它会给出错误的计时
time.monotonic()
- 这似乎是测量时间间隔最安全的选择 - 请注意,这根本不会给你当前时间,但它会给你两个时间点之间的正确差异
至于纳秒版本,只有在需要纳秒时才应该使用它们。
我对日期时间算法了解得越多,我就越头疼。
时间有很多种:
- 民用时间
- UTC
- 泰
- UNIX 时间
- 系统时间
- 线程时间
- CPU 时间
然后由于
时钟可以运行更快或更慢或者向后或向前跳跃- 夏令时
- 跨越时区
- 闰秒
- NTP 同步
- 广义相对论
如何处理这些又取决于:
- 操作系统
- 硬件
- 编程语言
所以有人可以告诉我,对于我的具体用例,最安全和最可靠的测量短间隔的方法吗?这是我正在做的事情:
我正在 Python (3.7.x) 中制作 游戏,我需要跟踪自某些事件以来已经过了多长时间。例如,玩家按住按钮多长时间,或者敌人发现玩家多长时间,或者关卡加载多长时间。时间尺度应该精确到毫秒(纳秒是多余的)。
以下是我想确保避免的情况:
你在深夜玩游戏。在你所在的时区,那天晚上,夏令时凌晨 2 点时钟拨快一小时,所以分钟数为:1:58、1:59、2:00、3:01、3:02。游戏中每个与时间相关的变量突然都增加了一个小时——它认为你已经按住那个按钮 1 小时 2 秒,而不是仅仅 2 秒。灾难接踵而至。
相同,但 IERS 决定在当天的某个时间插入或减去闰秒。您玩转场,所有时间变量都会增加或减少一秒。灾难接踵而至。
你在火车或飞机上玩游戏,当你跨越时区边界 and/or 国际日期变更线时,灾难接踵而至。
在上述情况下,游戏在某些硬件和操作系统上可以正常运行,但在其他情况下则不能。 IE。它在 Linux 而不是 Window 时中断,反之亦然。
而且我真的不能为这些编写测试,因为有问题的事件很少发生。我需要在第一时间把它做好。那么,我需要使用什么时间相关的功能呢?我知道有普通的旧 time.time()
,但也有令人眼花缭乱的其他选项,例如
time.clock()
time.perf_counter()
time.process_time()
time.monotonic()
- 然后是上述所有的纳秒变体。
通过阅读文档,似乎 time.monotonic()
就是我想要的。但是,如果阅读有关计时的所有细节教会了我什么的话,那就是这些东西从来都不像它们看起来的那样。曾几何时,我以为我知道 "second" 是什么。现在我不太确定了。
那么,如何确保我的游戏时钟正常工作?
specification of time module 是查找每一项详细信息的最佳位置。
在那里,你可以很容易地看到:
time.clock()
已弃用,应替换为其他函数time.process_time()
仅计算您的进程花费的 CPU 时间,因此它不适合测量挂钟时间(这是您需要的)time.perf_counter()
和time.process_time()
有同样的问题
time.time()
刚刚好,但如果用户修改当前时间,它会给出错误的计时time.monotonic()
- 这似乎是测量时间间隔最安全的选择 - 请注意,这根本不会给你当前时间,但它会给你两个时间点之间的正确差异
至于纳秒版本,只有在需要纳秒时才应该使用它们。