【问题标题】:Why does a conversion from np.datetime64 to float and back lead to a time difference?为什么从 np.datetime64 到 float 和 back 的转换会导致时差?
【发布时间】:2019-01-22 08:51:12
【问题描述】:

使用以下代码,在转换回 np.datetime64 后,我得到了两个小时的差异。

我怎样才能避免这种情况? (如果这应该是一个话题:我目前在中欧)

import pandas as pd
import numpy as np
import datetime

a = np.datetime64('2018-04-01T15:30:00').astype("float")
a
b = np.datetime64(datetime.datetime.fromtimestamp(a))
b

Out[18]: numpy.datetime64('2018-04-01T17:30:00.000000')

【问题讨论】:

    标签: python numpy


    【解决方案1】:

    问题不在于np.datetime64转换,而在于datetime.datetime.fromtimestamp

    Since Numpy 1.11, np.datetime64 是时区幼稚。它不再假定输入是当地时间,也不会打印当地时间。

    但是,datetime.datetime.fromtimestamp 确实假定为当地时间。来自docs

    返回POSIX时间戳对应的本地日期时间,如time.time()返回。如果可选参数 tz 为 None 或未指定,则将时间戳转换为平台的本地日期和时间,并且返回的 datetime 对象是 naive。

    您可以改用datetime.datetime.utcfromtimestamp

    >>> a = np.datetime64('2018-04-01T15:30:00').astype("float")
    >>> np.datetime64(datetime.datetime.utcfromtimestamp(a))
    numpy.datetime64('2018-04-01T15:30:00.000000')
    

    【讨论】:

      【解决方案2】:

      https://github.com/numpy/numpy/issues/3290

      从 1.7 开始,datetime64 尝试通过以下方式处理时区:

      • 假设所有 datetime64 对象都采用 UTC
      • 解析 ISO 8601 字符串时应用时区偏移
      • 在 ISO 字符串未指定 TZ 时应用 Locale 时区偏移量。
      • 在打印等时应用 Locale 时区偏移量。

      https://stackoverflow.com/a/18817656/7583612

      classmethod datetime.fromtimestamp(timestamp, tz=None)

      返回POSIX时间戳对应的本地日期时间, 例如由 time.time() 返回。如果可选参数 tz 为 None 或 未指定,时间戳转换为平台的本地日期 和时间,返回的 datetime 对象是幼稚的。

      否则 tz 必须是 tzinfo 子类的实例,并且 时间戳转换为 tz 的时区。在这种情况下,结果是 相当于 tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))

      【讨论】:

        【解决方案3】:

        回顾我的一些笔记,我发现了以下内容:

        import numpy
        dt64 = numpy.datetime64( "2011-11-11 14:23:56" )
        
        # dt64 is internally just some sort of int
        #      it has no fields, and very little support in numpy
        
        import datetime, time
        dtdt = dt64.astype(datetime.datetime)         # <<<<<<<< use this!
        dtdt.year
        dtdt.month
        dtdt.day
        
        # to convert back:
        dt64 = np.datetime64(dtdt)                    # <<<<<<<< use this too!
        dt64.item().strftime("%Y%b%d")
        

        模块 datetimetime 是普通的 python 模块:它们工作得相当好,有很多字段、转换和支持。

        datetime64numpy 中内置的未完全实现的子类型。它只是某种 64 位 int(?)(也许是 1970 年以来的秒数?)。 datetime64datetime.datetime 完全不同。如果将 datetime64 转换为浮点数并返回,则会损失很多精度(位)——因此会出现错误。

        (不是 numpy 的一部分)模块 datetime 还可以执行以下操作:

        # timedelta()
        delta = datetime.timedelta(days=11, hours=10, minutes=9, seconds=8)
        
        delta                   # datetime.timedelta(11, 36548)     # (days,seconds)
        delta.days
        delta.seconds
        delta.microseconds
        delta.total_seconds()   # 986948.0
        
        # arithmetic: +-*/
        #   2 timedelta's
        #   timedelta and datetime
        now = datetime.datetime.now()
        christmas = datetime.datetime(2019,12,25)
        delta = christmas - now
        

        所以让 numpy 有时将您的日期数据存储为 datetime64,但我建议不要使用 numpy 模块 datetime 来处理日期时间-算术。

        【讨论】:

          猜你喜欢
          • 2020-03-04
          • 2013-07-04
          • 1970-01-01
          • 2017-09-28
          • 1970-01-01
          • 1970-01-01
          • 2014-03-26
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多