快速解析非本地时区中的 Python 日期时间,并根据夏令时进行调整

2024-01-06

我需要快速将 ISO 8601 日期时间字符串(字符串中没有时区,但已知位于美国/太平洋时区)转换为 numpydatetime64 object.

如果我的机器处于美国/太平洋时间,我可以简单地运行numpy.datetime64(s)。但是,这假设没有时区的字符串位于本地时区。此外,我无法轻松指定 ISO 8601 格式的美国/太平洋时区,因为有时它是-0800有时-0700取决于夏令时。

到目前为止,我最快的解决方案是numpy.datetime64(pandas.Timestamp(s).tz_localize(tz='US/Pacific', ambiguous=True))。在我的机器上这需要 70μs。如果我能把这个速度提高至少一个数量级,那就太好了(numpy.datetime64(s)本地时间需要 4 µs,但如上所述是不正确的)。这可能吗?


首先请注意,如果没有偏移,某些当地时间及其日期时间 字符串是不明确的。例如,ISO 8601 日期时间字符串

2000-10-29T01:00:00-07:00
2000-10-29T01:00:00-08:00

两者都映射到相同的字符串2000-10-29T01:00:00当偏移量被移除时。

因此,重建一个独特的时区感知可能并不总是可能的 来自不带偏移量的日期时间字符串的日期时间。

然而,我们可以在这些模棱两可的情况下做出选择 情况并接受并非所有不明确的日期都会被正确转换。


如果您使用的是 Unix,则可以使用时间.tzset https://docs.python.org/2/library/time.html#time.tzset更改进程的本地时区:

import os
import time
os.environ['TZ'] = tz
time.tzset()

然后,您可以使用以下命令将日期时间字符串转换为 NumPy datetime64

def using_tzset(date_strings, tz):
    os.environ['TZ'] = tz
    time.tzset()
    return np.array(date_strings, dtype='datetime64[ns]')

但请注意using_tzset并不总是产生与您提出的方法相同的值:

import os
import time
import numpy as np
import pandas as pd

tz = 'US/Pacific'
N = 10**5
dates = pd.date_range('2000-1-1', periods=N, freq='H', tz=tz)
date_strings_tz = dates.format(formatter=lambda x: x.isoformat())
date_strings = [d.rsplit('-', 1)[0] for d in date_strings_tz]

def orig(date_strings, tz):
    return [np.datetime64(pd.Timestamp(s, tz=tz)) for s in date_strings]

def using_tzset(date_strings, tz):
    os.environ['TZ'] = tz
    time.tzset()
    return np.array(date_strings, dtype='datetime64[ns]')

npdates = dates.asi8.view('datetime64[ns]')
x = np.array(orig(date_strings, tz))
y = using_tzset(date_strings, tz)
df = pd.DataFrame({'dates': npdates, 'str': date_strings_tz, 'orig': x, 'using_tzset': y})

这表明原来的方法,orig,无法恢复原始日期 172 次:

print((df['dates'] != df['orig']).sum())
172

while using_tzset失败11次:

print((df['dates'] != df['using_tzset']).sum())
11  

但请注意,这 11 倍using_tzset失败是由于 DST 导致本地日期时间不明确。

这显示了一些差异:

mask = df['dates'] != df['using_tzset']
idx = np.where(mask.shift(1) | mask)[0]
print(df[['dates', 'str', 'using_tzset']].iloc[idx]).head(6)

#                     dates                        str         using_tzset
# 7248  2000-10-29 08:00:00  2000-10-29T01:00:00-07:00 2000-10-29 08:00:00
# 7249  2000-10-29 09:00:00  2000-10-29T01:00:00-08:00 2000-10-29 08:00:00
# 15984 2001-10-28 08:00:00  2001-10-28T01:00:00-07:00 2001-10-28 08:00:00
# 15985 2001-10-28 09:00:00  2001-10-28T01:00:00-08:00 2001-10-28 08:00:00
# 24720 2002-10-27 08:00:00  2002-10-27T01:00:00-07:00 2002-10-27 08:00:00
# 24721 2002-10-27 09:00:00  2002-10-27T01:00:00-08:00 2002-10-27 08:00:00

正如您所看到的,当日期字符串在str柱子 当偏移量被移除时,就会变得不明确。

So using_tzset在不明确的日期时间之前似乎都能产生正确的结果。


这是一个 timeit 基准比较orig and using_tzset:

In [95]: %timeit orig(date_strings, tz)
1 loops, best of 3: 5.43 s per loop

In [96]: %timeit using_tzset(date_strings, tz)
10 loops, best of 3: 41.7 ms per loop

So using_tzset比快 100 倍以上orig当N=10**5时。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速解析非本地时区中的 Python 日期时间,并根据夏令时进行调整 的相关文章

随机推荐

  • 合并具有相似名称的列

    我有一个带有非常烦人的变量名的数据框 基本上我对同一变量的观察分布在变量 g1 param1 g2 param1 g3 param1 等中 我想将它们全部加入到 1 个名为 param1 的变量 列中 g1 param1 g2 param1
  • 谷歌地点 API 是免费的吗? [关闭]

    Closed 这个问题是与编程或软件开发无关 help closed questions 目前不接受答案 我想用谷歌地点 API在网络应用程序中 我只是想确认API是否免费 如果是付费功能那么收费是多少 您可以查看每个API的定价here
  • C# 应用程序在远程上总是冻结

    我正在开发一个 C 应用程序 Net 3 5 Win Forms 该应用程序在服务器上运行 并由用户使用远程桌面访问 应用程序在远程计算机上看似随机的情况下一直冻结 即所有 GUI 组件都变成白色 任务管理器报告应用程序没有响应 但在本地运
  • 如何通过邮递员发送graphql查询?

    I use POST type URL http graphql Body query query noteTypes name label labelColor groupName groupLabel imageUrl 但它返回 mes
  • SAPUI5 表达式绑定

    是否可以将控件属性绑定到具有动态属性名称的模型 例如存储在另一个模型字段中 我以为我们可以使用 SAPUI5表达式绑定 https sapui5 hana ondemand com docs guide daf6852a04b44d1189
  • 在 Android 中的 BOOT_COMPLETE 上,未从 AndroidManifest 调用 BroadcastReceiver

    在我的 Android 应用程序中 我想运行Service无需打开 运行我的应用程序 为此我延长了BroadcastReciever班级 但是这个BroadcastReceiver类未被调用AndroidManifest xml on BO
  • 使用 jquery 拖放

    我有两个基于 jquery 的列表 示例是here http devheart org examples jquery customizable layout using drag and drop 2 saving and loading
  • 在 C# 桌面应用程序中存储我的 Amazon 凭证

    我正在考虑在桌面应用程序中使用 Amazon S3 和 simpleDB 我遇到的主要问题是我需要将我的 aws 凭证存储在应用程序中或使用其他方案 我猜想将它们存储在应用程序中是不可能的 因为它们很容易被挑选出来 另一种选择是创建一个 W
  • 如何在 Angular.js 中解析 Int

    也许 这是最简单的事情 但我无法将字符串解析为角度中的 Int 我正在尝试做的事情
  • MISRA C++ 2008 规则 5-2-7 违规:具有指针类型的对象不得直接或间接转换为不相关的指针类型

    在以下示例中 void bad function char t ptr 0 MISRA doesn t complains here it allows cast of char to void pointer void p2 ptr th
  • Magento 产品使用 SQL 查询从数据库导入

    Magento 在其数据库系统中使用 EAV 结构 我有这个查询 它为我提供了我的 magento 商店中的产品 ID 和产品名称 SELECT e entity id AS product id var value AS product
  • 如何以 SVG 形式获取 matplotlib 图的输出?

    我需要获取 matplotlib 图的输出并将其转换为可以在激光切割机上使用的 SVG 路径 import matplotlib pyplot as plt import numpy as np x np arange 0 100 0 00
  • Android 应用程序从 linkedin 访问令牌

    首先 是否可以使用 facebook twitter 等 Android 应用程序添加 linkedin 我读过很多博客 但无法在我的应用程序中实现 linkedin 我已达到应用程序的用户授权流程 用户输入其用户名和密码 但是当他输入 5
  • Firebase onCreate 触发器:无法获取除 UNAUTHENTICATED 之外的 authType

    使用具有以下规则的 Firebase 实时数据库 rules messages read auth null write auth null 并且 将此触发器定义为 exports localOnCreate functions datab
  • 扩展 Google 地图范围,使 div 叠加层不覆盖任何标记

    在我正在开发的 Google 地图混搭中 地图为 100 宽 高度几乎为 100 并且我有一个水平透明 div 它使用 z index 和 CSS 覆盖地图的左侧 当我动态添加标记时 我从一个空的 Bounds 对象开始 然后将其一一扩展以
  • 隐藏软键盘

    我需要能够隐藏软键盘以响应单击按钮 我看过很多关于这个主题的帖子 似乎解决方案是使用InputMethodManager 但我一直无法让它为我工作 据说以下将隐藏软键盘 InputMethodManager inputManager Inp
  • 如何设置 CSS、JS 和图像的过期时间?

    我最近使用 firebug 上的 pagespeed 插件分析了我的网站 它建议我设置 CSS JS 和图像文件的过期时间 我想知道 我该怎么做 当我运行 PageSpeed Addon 时 我用它来修复完全相同的问题
  • 使用 asyncio 实现非阻塞 I/O

    我正在尝试使用 Pygame 和 asyncio 编写一个网络游戏 但我不知道如何避免挂起读取 这是我为客户提供的代码 asyncio coroutine def handle client print Connected reader w
  • glmnet 的公式接口

    在过去的几个月里 我参与了许多项目 在这些项目中我使用了glmnet适合弹性网模型的封装 它很棒 但与大多数 R 建模函数相比 其界面相当简陋 特别是 您必须给出响应向量和预测矩阵 而不是指定公式和数据框 您还会失去常规界面提供的许多生活质
  • 快速解析非本地时区中的 Python 日期时间,并根据夏令时进行调整

    我需要快速将 ISO 8601 日期时间字符串 字符串中没有时区 但已知位于美国 太平洋时区 转换为 numpydatetime64 object 如果我的机器处于美国 太平洋时间 我可以简单地运行numpy datetime64 s 但是