跳转到主要内容

时间对象子类化datetime,允许重定向本地时钟机制

项目描述

此软件包提供了一种时间抽象机制,允许将作为参考使用的代码重定向到本地时区和真实时间。

这允许测试依赖时钟的代码。请参阅入门部分以获取更详细的解释。

此外,作为对旧版datetime对象的抽象,sact.epoch.Time中提供的Time对象提供了一些常用的辅助函数,并强制该对象始终提供时区。

sact.epoch对象将对以下情况有所帮助

  • 如果您的应用程序管理2+个不同的时区(例如:UTC和本地时区),并且您已经厌倦了在此问题上的旧版“天真”datetime对象。

  • 如果您想要能够在测试目的下重定向系统调用到本地时间或应用程序的本地时区。

内容

时间

datetime的子类,表示时间的绝对瞬间(带时区)。它强制datetime的使用意识到时区。此外,Time.now()将向Zope组件架构注册表请求时钟实用工具以提供真实时间。

时钟

时钟对象是获取Time对象的通用参考。默认时钟是我们常见的正常时钟,但ZCA允许替换引用并提供其他类型的时钟,如sact.epoch.ManageableClock,它可以被管理(这意味着它可以停止、设置、在未来或过去转换)。

时区

TimeZone对象代表特定的时区,sact.epoch.TzLocal()将获取本地系统时区。此调用也可以通过ZCA进行重定向,以提供另一个TimeZone。 sact.epoch.testTimeZone 是一个常用的重定向目标时区,用于帮助测试代码。

入门指南

sact.epoch.Time 是作为 datetime.datetime 的替代品。作为这个子类的后代,它将提供相同的功能,因此可以在几乎任何使用 datetime.datetime 的地方使用它。

此外,使用 sact.epoch.Time 确保

  • 所有实例都将获取时区。而对于 datetime 对象来说并不是这样。

  • .now() 方法将使用Zope组件架构注册表来获取一个负责提供实时数据的通用工具。这允许简单的覆盖机制。

从datetime获取时间戳

假设您有一些使用 datetime.datetime.now() 的代码

>>> import datetime
>>> now = datetime.datetime.now()

第一个问题:如果这个变量是用来表示存储在数据库中的UTC时间的时间。

如何从datetime获取UTC时间戳?(参见:http://bugs.python.org/issue1457227

这是一个常见问题。(参见:http://stackoverflow.com/questions/5067218/get-utc-timestamp-in-python-with-datetime/5499906#5499906

答案是 datetime.datetime 对象可能是无知的,这意味着它们不知道时区。因此,除非你自己能猜出时区,否则无法从这种形式的datetime获取UTC时间戳。

希望您的系统在创建datetime对象和您想要获取时间戳的时刻之间没有改变时区,如果是这样,您可以使用它来安全地使用

>>> import sact.epoch.utils
>>> utc_timestamp = sact.epoch.utils.dt2ts(now)

dt2ts 将向您的系统请求当前时区EPOCH与提供的datetime之间的秒数。这就是为什么您必须确保在创建datetime对象时系统上具有与运行此函数时相同的TimeZone。

没有doctest提供给您查看变量 utc_timestamp 的内容,因为输出取决于当前时间。这往往是您会遇到的问题:拥有依赖于当前日期的复杂代码,您如何测试它?这正是sact.epoch.Time的目的。

强制只使用有感知的datetime

很快,您会问自己:如果它们在许多情况下都不能使用,无知 datetime.datetime 对象有什么用?

答案是:无知 datetime.datetime 对象没有用。

有感知的datetime对象,如 sact.epoch.Time,包含所有附加信息,允许

  • 获取UTC时间戳

  • 比较两个 Time 对象,无论它们的时区是什么。

使用无知的datetime甚至可能被认为是有害的。 sact.epoch.Time 将确保您的所有对象都是时区感知的。默认情况下,时区甚至不会依赖于您系统的本地时间,而是存储在UTC时区。

datetime对象

>>> from __future__ import print_function

>>> print(repr(datetime.datetime.now().tzinfo))
None
>>> print(repr(datetime.datetime(1970, 1, 1, 1, 1).tzinfo))
None

相比之下,sact.epoch.Time 对象将始终设置一个时区

>>> print(repr(sact.epoch.Time.now().tzinfo))
<TimeZone: UTC>
>>> print(repr(sact.epoch.Time(1970, 1, 1, 1, 1).tzinfo))
<TimeZone: UTC>

当然,由于Time对象是有感知的,因此有一个简单的 timestamp 属性可用

>>> epoch = sact.epoch.Time(1970, 1, 1, 0, 0)
>>> epoch.timestamp
0

重定向时间

如果您使用 sact.epoch.Time.now() 代替 datetime.datetime.now(),则您的代码将具有重定向实时参考的接口,而无需触摸系统时钟。

假设您的代码是

>>> db_timestamp = epoch.timestamp
>>> def is_it_ok():
...    now = sact.epoch.Time.now().timestamp
...    print(0 == ((now - db_timestamp) % 2))

is_it_ok 函数代码应该打印 True,如果当前时间和纪元之间的秒数是奇数。

这种函数类型在您使用 datetime.datetime.now() 时很难测试。整个应用程序将广泛使用系统时钟,除非您用 sact.epoch.Time.now() 替换 datetime,否则将很难测试。

以下是该函数的测试方法

>>> clock = sact.epoch.clock.ManageableClock()

默认情况下,时钟跟随系统时钟。让我们停止它并将它设置为纪元(更多关于可管理的时钟,请参阅类 ManageableClock 的文档字符串)

>>> clock.stop()
>>> clock.ts = 0

现在让我们使用 ZCA 声明这个时钟作为新的参考时钟

>>> from zope.component import globalSiteManager as gsm
>>> gsm.registerUtility(clock)

我们现在可以测试该函数了

>>> sact.epoch.Time.now().timestamp
0
>>> is_it_ok()
True

>>> clock.ts = 1
>>> sact.epoch.Time.now().timestamp
1
>>> is_it_ok()
False

请注意,ManageableClock 有一个 wait 方法

>>> clock.wait(minutes=1)
>>> sact.epoch.Time.now().timestamp
61
>>> is_it_ok()
False

当然,clock.wait 的执行是立即的。您可以将 datetime.timedelta 用作 wait 的参数或任何可以发送给 datetime.timedelta 构造函数的关键字参数(这包括 dayssecondsmicrosecondsmillisecondsminuteshoursweeks,自 Python 2.7.1 版本起,cf:https://docs.pythonlang.cn/library/datetime.html#datetime.timedelta

改变系统时区

当向用户显示时间时,显示本地时区的时间会更受欢迎

>>> def what_time_is_it():
...     print(sact.epoch.Time.now().local.iso)

注意使用属性 local,它返回一个新的 Time 实例,设置为相同的时间点,但位于系统本地时区,以及 iso 属性,它返回 Time 对象的 ISO 字符串表示。

local 属性使用 sact.epoch.TzLocal(),它负责提供系统本地时区

>>> sact.epoch.TzLocal()
<TimeZone: System>

让我们使用 ZCA 将 TzLocal 机制改变为获取系统本地时区

>>> from sact.epoch import testTimeZone
>>> from sact.epoch.interfaces import ITimeZone

>>> gsm.registerUtility(testTimeZone, ITimeZone, name='local')

现在我们可以测试我们的函数了

>>> clock.ts = 0
>>> what_time_is_it()
1970-01-01 00:05:00+00:05

测试时区 testTimeZone 非常特殊且具有识别性:它在 UTC 上有恒定的 +5 分钟偏移

内部,对 TzLocal() 的调用已被转移

>>> sact.epoch.TzLocal()
<TimeZone: Test>

项目详细信息


下载文件

下载适合您平台的文件。如果您不确定选择哪个,请了解有关 安装包 的更多信息。

源分发

sact.epoch-1.3.0.tar.gz (36.6 kB 查看散列)

上传时间

由以下支持

AWS AWS 云计算和安全赞助商 Datadog Datadog 监控 Fastly Fastly CDN Google Google 下载分析 Microsoft Microsoft PSF 赞助商 Pingdom Pingdom 监控 Sentry Sentry 错误记录 StatusPage StatusPage 状态页面