当前位置: 首页 > 知识库问答 >
问题:

转换熊猫时区感知DateTimeIndex到天真的时间戳,但在某些时区

金秦斩
2023-03-14

您可以使用函数tz_localize使时间戳或DateTimeIndex具有时区意识,但如何做到相反:如何将具有时区意识的时间戳转换为原始时间戳,同时保留其时区?

例如:

In [82]: t = pd.date_range(start="2013-05-18 12:00:00", periods=10, freq='s', tz="Europe/Brussels")

In [83]: t
Out[83]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 12:00:00, ..., 2013-05-18 12:00:09]
Length: 10, Freq: S, Timezone: Europe/Brussels

我可以通过将时区设置为“无”来删除它,但随后结果将转换为UTC(12点变为10点):

In [86]: t.tz = None

In [87]: t
Out[87]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 10:00:00, ..., 2013-05-18 10:00:09]
Length: 10, Freq: S, Timezone: None

是否有其他方法可以将DateTimeIndex转换为时区naive,但同时保留其设置的时区?

关于我问这个问题的原因,有一些背景:我想处理时区原始时间序列(以避免与时区的额外麻烦,我在处理的情况下不需要它们)。
但出于某种原因,我必须处理本地时区(欧洲/布鲁塞尔)中的时区感知时间序列。由于我的所有其他数据都是未经验证的时区(但在我的本地时区中表示),我想将此timeseries转换为未经验证的,以进一步使用它,但它也必须在我的本地时区中表示(因此,只需删除时区信息,而不将用户可见时间转换为UTC)。

我知道时间实际上是作为UTC存储在内部的,只有当你表示它时才会转换到另一个时区,所以当我想“离域”它时,必须有某种转换。例如,使用python datetime模块,您可以像这样“删除”时区:

In [119]: d = pd.Timestamp("2013-05-18 12:00:00", tz="Europe/Brussels")

In [120]: d
Out[120]: <Timestamp: 2013-05-18 12:00:00+0200 CEST, tz=Europe/Brussels>

In [121]: d.replace(tzinfo=None)
Out[121]: <Timestamp: 2013-05-18 12:00:00> 

因此,基于此,我可以执行以下操作,但我认为在处理较大的时间序列时,这不会非常有效:

In [124]: t
Out[124]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 12:00:00, ..., 2013-05-18 12:00:09]
Length: 10, Freq: S, Timezone: Europe/Brussels

In [125]: pd.DatetimeIndex([i.replace(tzinfo=None) for i in t])
Out[125]: 
<class 'pandas.tseries.index.DatetimeIndex'>
[2013-05-18 12:00:00, ..., 2013-05-18 12:00:09]
Length: 10, Freq: None, Timezone: None

共有3个答案

潘佐
2023-03-14

我认为你不可能以比你提议的更有效的方式实现你想要的。

潜在的问题是时间戳(如您所知)由两部分组成。表示UTC时间和时区、tz_信息的数据。在屏幕上打印时区时,时区信息仅用于显示目的。在显示时,数据会适当偏移,并将01:00(或类似值)添加到字符串中。剥离tz_info值(使用tz_convert(tz=None))实际上不会更改表示时间戳原始部分的数据

因此,您想要做的唯一方法是修改基础数据(pandas不允许这样做…DatetimeIndex是不可变的--请参阅DatetimeIndex上的帮助),或者创建一组新的时间戳对象并将它们包装到一个新的DatetimeIndex中。您的解决方案可执行以下操作:

pd.DatetimeIndex([i.replace(tzinfo=None) for i in t])

以下是Timestampreplace方法(参见tslib.pyx),供参考:

def replace(self, **kwds):
    return Timestamp(datetime.replace(self, **kwds),
                     offset=self.offset)

您可以参考datetime.datetime上的文档,查看datetime.datetime.replace还创建了一个新对象。

如果可以,提高效率的最佳选择是修改数据源,使其(错误地)报告时间戳而不带时区。你提到:

我想使用时区天真的时间序列(为了避免时区带来的额外麻烦,我不需要它们来处理我正在处理的案件)

我很好奇你指的是什么额外的麻烦。我建议作为所有软件开发的一般规则,将时间戳“naive values”保留为UTC。没有什么比查看两个不同的int64值更糟糕的了,它们不知道属于哪个时区。如果您始终使用UTC作为内部存储,那么您将避免无数的麻烦。我的口头禅是时区仅用于人类I/O。

常雪风
2023-03-14

因为我总是很难记住,快速总结一下它们各自的作用:

>>> pd.Timestamp.now()  # naive local time
Timestamp('2019-10-07 10:30:19.428748')

>>> pd.Timestamp.utcnow()  # tz aware UTC
Timestamp('2019-10-07 08:30:19.428748+0000', tz='UTC')

>>> pd.Timestamp.now(tz='Europe/Brussels')  # tz aware local time
Timestamp('2019-10-07 10:30:19.428748+0200', tz='Europe/Brussels')

>>> pd.Timestamp.now(tz='Europe/Brussels').tz_localize(None)  # naive local time
Timestamp('2019-10-07 10:30:19.428748')

>>> pd.Timestamp.now(tz='Europe/Brussels').tz_convert(None)  # naive UTC
Timestamp('2019-10-07 08:30:19.428748')

>>> pd.Timestamp.utcnow().tz_localize(None)  # naive UTC
Timestamp('2019-10-07 08:30:19.428748')

>>> pd.Timestamp.utcnow().tz_convert(None)  # naive UTC
Timestamp('2019-10-07 08:30:19.428748')
傅阿苏
2023-03-14

为了回答我自己的问题,这个功能已经被添加到熊猫中。从熊猫0.15.0开始,您可以使用tz_localize(无)删除导致本地时间的时区。
请参阅whsnew条目:http://pandas.pydata.org/pandas-docs/stable/whatsnew.html#timezone-handling-improvements

以我上面的例子:

In [4]: t = pd.date_range(start="2013-05-18 12:00:00", periods=2, freq='H',
                          tz= "Europe/Brussels")

In [5]: t
Out[5]: DatetimeIndex(['2013-05-18 12:00:00+02:00', '2013-05-18 13:00:00+02:00'],
                       dtype='datetime64[ns, Europe/Brussels]', freq='H')

使用tz\u localize(None)删除时区信息,从而生成原始本地时间:

In [6]: t.tz_localize(None)
Out[6]: DatetimeIndex(['2013-05-18 12:00:00', '2013-05-18 13:00:00'], 
                      dtype='datetime64[ns]', freq='H')

此外,您还可以使用tz_convert(None)删除时区信息,但将其转换为UTC,从而生成原始UTC时间:

In [7]: t.tz_convert(None)
Out[7]: DatetimeIndex(['2013-05-18 10:00:00', '2013-05-18 11:00:00'], 
                      dtype='datetime64[ns]', freq='H')

这比日期时间更有效。替换解决方案:

In [31]: t = pd.date_range(start="2013-05-18 12:00:00", periods=10000, freq='H',
                           tz="Europe/Brussels")

In [32]: %timeit t.tz_localize(None)
1000 loops, best of 3: 233 µs per loop

In [33]: %timeit pd.DatetimeIndex([i.replace(tzinfo=None) for i in t])
10 loops, best of 3: 99.7 ms per loop

 类似资料:
  • 问题内容: 考虑到python中的pandas数据帧具有名为integer类型的列,我可以使用以下指令将其转换为格式。 因此,该列现在具有以下条目:。 将字符串恢复为整数时间戳值(代表从过去的秒数)的命令是什么? 我检查了但找不到转换实用程序,因此无法使用它。 此转换有实用程序吗? 问题答案: 您可以使用类型转换为int并将其除以以获取unix纪元开始的秒数。

  • 问题内容: 如何将时区感知日期时间对象转换为本地时区的等效非时区感知日期时间? 我的特定应用程序使用Django(尽管这实际上是一个通用的Python问题): .... 这导致Django抛出错误: 我需要的是: 什么会SOME_FUNCTION是什么? 问题答案: 通常,要将任意时区感知日期时间转换为原始(本地)日期时间,我将使用模块并将其转换为本地时间,并使日期时间变为原始状态: 但是由于你的

  • 返回我女巫是错误的。 但接下来的查询如下: 我看对日期

  • 从我的数据库我检索值为: 我想要上面的: 我试着用当前的时间戳跟踪 实际时间戳:2018年6月22日星期五16:07:35 更新了,我不想更新,有没有办法保持原样?

  • 问题内容: 将熊猫的DateTimeIndex转换为Unix时间(可迭代)的惯用方式是什么?这可能不是要走的路: 问题答案: 由于是引擎盖下,你可以做转换没有理解(要快得多)。

  • 我想将时间戳转换为。 这是我到目前为止已经实现的,但是它给了我错误的月份 任何帮助将不胜感激。