问题描述
以下哪种方法是将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 Date格式存储在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'>
解决方法
我从未使用过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