【问题标题】:PyMongo/Python/Airflow - Convert CST Date/DateTime to UTC and store in MongoDB in ISO format?PyMongo/Python/Airflow - 将 CST 日期/日期时间转换为 UTC 并以 ISO 格式存储在 MongoDB 中?
【发布时间】:2020-12-25 06:47:47
【问题描述】:

将 CST 日期和/或日期时间字段与 DST 感知设置一起转换为 UTC 并以 Python/PyMongo 中的 ISO 格式存储在 MongoDB 中的正确、理想或首选方法是什么?源日期/日期时间字段可以来自任何时区(现在我们知道它的 CST),我需要将它们全部转换为 UTC 并存储到目标 MongoDB。

根据 MongoDB 文档,MongoDB 默认以 UTC 存储时间,并将任何本地时间表示形式转换为这种形式。必须对某些未修改的本地时间值进行操作或报告的应用程序可以将时区与 UTC 时间戳一起存储,并在其应用程序逻辑中计算原始本地时间。

例子:

方法#1:使用时间戳(定义本地时区)

from datetime import datetime
import pytz
local_timezone = pytz.timezone("US/Central")
utc_datetime = local_timezone.localize(datetime.strptime ("1/2/2017 12:43 pm",'%m/%d/%Y %H:%M %p'),is_dst=True).astimezone(pytz.utc)
print(utc_datetime)
print(type(utc_datetime))

2017-01-02 18:43:00+00:00
<class 'datetime.datetime'>

没有时间戳,即只有日期: - 它在时间戳和 DST 5 小时期间添加 6 小时的偏移值。删除或不删除 astimezone(pytz.utc) ,它会返回日期/时间,如 2017-01-02 00:00:00-06:00 即显示 -6 小时偏移差异。我们真的应该使用 astimezeon(pytz.utc) 吗??

from datetime import datetime
import pytz
local_timezone = pytz.timezone("US/Central")
utc_datetime = local_timezone.localize(datetime.strptime ("1/2/2017",'%m/%d/%Y'),is_dst=True).astimezone(pytz.utc)
print(utc_datetime)
print(type(utc_datetime))

2017-01-02 06:00:00+00:00
<class 'datetime.datetime'>

方法#2:带时间戳(未定义本地时区)

from datetime import datetime, timezone
utc_datetime=datetime.utcfromtimestamp(datetime.strptime ("1/2/2017 12:43 pm",'%m/%d/%Y %H:%M %p').replace(tzinfo = timezone.utc).timestamp())
print(utc_datetime)
print(type(utc_datetime))

2017-01-02 12:43:00
<class 'datetime.datetime'>

没有时间戳,即只有日期部分 - 没有偏移

from datetime import datetime, timezone
utc_datetime=datetime.utcfromtimestamp(datetime.strptime ("1/2/2017",'%m/%d/%Y').replace(tzinfo = timezone.utc).timestamp())
print(utc_datetime)
print(type(utc_datetime))

2017-01-02 00:00:00
<class 'datetime.datetime'>

加载到 MongoDB 后 - 它会在日期/时间戳的末尾添加一个“Z”。启动与 MongoClient 的连接时是否还应添加“tz_aware=True”?

ISOFormat - 将 utc 时间戳更改为 isoformat() 返回并在 MongoDB 中作为字符串而不是日期加载。那么,我们如何确保它仍然以 ISO 日期格式存储在 MongoDB 中?

utc_datetime_iso=datetime.utcfromtimestamp(datetime.strptime ("1/2/2017",'%m/%d/%Y').replace(tzinfo = timezone.utc).timestamp()).**isoformat()**
print(utc_datetime_iso)
print(type(utc_datetime_iso))

2017-01-02T00:00:00
<class 'str'>

【问题讨论】:

  • 将这些值插入 MongoDB 并检查实际插入的内容(最好使用 mongo shell 之类的本机工具)
  • 我在上面也提到过,它在日期时间的末尾添加了一个“Z”,如下所示:2017-01-02 06:00:00Z,但它来自 robo3t mongodb UI 界面,haven '未从 Mongo 本机 shell/CLI 检查。我很想知道从本地时区处理 UTC 转换、存储到 MongoDB 的最佳和推荐做法是什么 - 格式和所有 - 以防万一这些数据要在全球范围内用于报告目的。
  • 旁注:考虑使用pytzutcfromtimestamp
  • 那么,Python 中将本地时区转换为 UTC 的另一种选择是什么?在上述两种方法中,我使用 pytz 而不是 utcfromtimestamp,根据这两个链接:- [link] (julien.danjou.info/python-and-timezones) 和 [link] (medium.com/@jmarhee/…)。
  • 您可以简单地使用 datetime 模块中的timezone.utc,例如获取 UTC 的当地时间:datetime.now().astimezone(timezone.utc)。如果您需要使用 本地时间 以外的其他时区,请查看 dateutilzoneinfo (Python 3.9)。

标签: python-3.x mongodb utc python-datetime pymongo-3.x


【解决方案1】:

我从来没有使用过python,所以我只能给出一些一般性的说明。

从不将日期/时间值存储为字符串,使用正确的 Date 对象。将日期/时间值存储为字符串通常是设计失败。

MongoDB 中的所有 Date 值都以 UTC 格式存储 - 始终且仅。一些客户端应用程序将 UTC 隐式转换为本地时间并显示本地值,但在 MongoDB 内部它始终是 UTC。

如果你运行db.collection.insertOne({ts: ISODate("2020-09-07T14:00:00+02:00")})然后MongoDB存储ISODate("2020-09-07T12:00:00Z"),原来的时区信息会丢失。如果您需要保留原始时区,则必须将其存储在单独的字段中。

ISODate 只是new Date 的别名。但是,有区别。如果您未指定任何时区(例如 "2020-09-07T14:00:00"),则 new Date() 假定为本地时间,但 ISODate() 假定为 UTC 时间。我不知道python内部使用的是哪种方法。

所以,new Date("2020-09-07T14:00:00") 的结果是 2020-09-07 12:00:00Z,而 ISODate("2020-09-07T14:00:00") 的结果是 2020-09-07 14:00:00Z

【讨论】:

    猜你喜欢
    • 2020-05-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-14
    • 2023-03-15
    • 2018-08-31
    • 2016-04-03
    相关资源
    最近更新 更多