bar*_*uda 2 python datetime firebase google-cloud-firestore
我正在尝试使用 python 将 firestore 时间戳转换为毫秒或日期格式,以使用此日期执行计算。尝试将其解析为日期返回。
TypeError: strptime() argument 1 must be str, not DatetimeWithNanoseconds.
如何在 python 中将 Firestore 时间戳转换为毫秒/日期格式?我需要这个来执行计算。
docs = db.collection(u'status').stream()
for doc in docs:
doc_data = doc.to_dict()
# TypeError: strptime() argument 1 must be str, not DatetimeWithNanoseconds
utc_time = datetime.strptime(doc_data['start_date'], "%Y-%m-%dT%H:%M:%S.%fZ")
Run Code Online (Sandbox Code Playgroud)
Voy*_*Voy 16
转换DatetimeWithNanoseconds为datetime.datetime:
datetime.datetime.fromtimestamp(datetime_with_nanoseconds.timestamp())
Run Code Online (Sandbox Code Playgroud)
尽管没有直接解决转换为日期格式的问题,但仍将这个答案留在这里,因为这是有关此转换的唯一帖子,而且我还没有在任何地方看到这个简单的直接解决方案。
正如卢克的回答所暗示的,您可以使用 的所有常用方法datetime和 的值DatetimeWithNanoseconds,因为它是一个子类。例如,您可以获取doc_data['start_date'].timestamp()自 1970-01-01 以来的以秒为单位的时间(包括小数秒)。
然而,通过试验和查看DatetimeWithNanoseconds 的实现,我注意到开发人员应该注意的一些问题(并且可能是 Google 应该修复的)。
DatetimeWithNanoseconds将只读nanosecond属性添加到datetime,但保留其microsecond属性。其目的似乎是您可以在创建对象时设置其中之一,但不能同时设置两者,然后读取其中之一。使用DatetimeWithNanoseconds构造函数时,可以设置microsecond或nanosecond,但不能同时设置两者(如果设置nanosecond,则必须将其指定为关键字参数)。如果您尝试同时设置两者,则会引发异常。如果您仅设置nanosecond,它会正确设置microsecond为nanosecond / 1000,向下舍入。如果您仅设置microsecond,则它会设置microsecond,但nanosecond设置为零。
>>> from google.api_core.datetime_helpers import DatetimeWithNanoseconds
>>> d1 = DatetimeWithNanoseconds(2020, 6, 22, 17, 1, 30, 12345)
>>> d1.microsecond
12345
>>> d1.nanosecond
0
>>> d2 = DatetimeWithNanoseconds(2020, 6, 22, 17, 1, 30, nanosecond=1234567)
>>> d2.microsecond
1234
>>> d2.nanosecond
1234567
Run Code Online (Sandbox Code Playgroud)
如果您以其他方式构造 a DatetimeWithNanoseconds,例如,您总是会得到一个设置为零的DatetimeWithNanoseconds.now()值。nanosecond
>>> now = DatetimeWithNanoseconds.now()
>>> now.microsecond
51570
>>> now.nanosecond
0
Run Code Online (Sandbox Code Playgroud)
从 Firestore 获取文档时获得的值似乎总是设置nanosecond为零!因此,如果我要获取带有时间戳的文档,然后将其写回 Firestore,则会丢失精度。(尽管我承认我使用的是一个相当旧的版本firebase-admin,所以它可能已在更新的版本中修复。)
我目前正在做类似的事情来从时间戳中提取秒和纳秒(我在不确定时间戳是 adatetime还是 a 的情况下使用它DatetimeWithNanoseconds):
def get_seconds_and_nanoseconds(val):
if isinstance(val, datetime_helpers.DatetimeWithNanoseconds) and val.nanosecond:
return {
'nanoseconds': val.nanosecond,
'seconds': int(val.timestamp()),
}
if isinstance(val, datetime):
return {
'nanoseconds': 1000 * int(val.microsecond),
'seconds': int(val.timestamp()),
}
raise TypeError(f'Not a datetime or DatetimeWithNanoseconds')
Run Code Online (Sandbox Code Playgroud)
为了DatetimeWithNanoseconds从秒和纳秒构建正确的值,我这样做:
def datetime_with_nanoseconds(seconds, nanoseconds):
dt = datetime.fromtimestamp(seconds, tz=timezone.utc)
dtnanos = datetime_helpers.DatetimeWithNanoseconds(
dt.year,
dt.month,
dt.day,
dt.hour,
dt.minute,
dt.second,
nanosecond=nanoseconds,
tzinfo=dt.tzinfo,
)
return dtnanos
Run Code Online (Sandbox Code Playgroud)
它很难看,但我还没有找到更简洁的方法。
尝试这个解决方案
try:
utc_time = strptime(''.join(str(doc_data['start_date']).rsplit(':', 1)), "%Y-%m-%d %H:%M:%S.%f%z")
except Exception as e:
if type(e) is ValueError:
utc_time = strptime(''.join(str(doc_data['start_date']).rsplit(':', 1)), "%Y-%m-%d %H:%M:%S%z")
else :
print(e)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
5110 次 |
| 最近记录: |