将pandas时间戳转换时区

21 投票
3 回答
55576 浏览
提问于 2025-04-19 16:32

我在一个数据框中有以下内容:

> df['timestamps'].loc[0]
Timestamp('2014-09-02 20:24:00')

我知道它使用的时区(我认为是格林威治标准时间),我想把整个列转换成东部标准时间。我该如何在Pandas中做到这一点呢?

为了参考,我找到了一些其他的讨论:

但它们处理的是datetime时间戳。例如:

> datetime.datetime.fromtimestamp(df['timestamps'].loc[0], tz=None)
returns:

TypeError                                 Traceback (most recent call last)
----> 2 datetime.datetime.fromtimestamp(ts, tz=None)

TypeError: an integer is required (got type Timestamp)

3 个回答

0

这是一个将UTC时间(最初来自Unix时间)转换为美国东部时间的例子。

这个方法是以向量化的方式运行的,所以速度非常快:处理数百万行数据只需几秒钟。

在Python 3.9上测试过。

df = pd.DataFrame({"timestamp": [Timestamp("2017-01-03 14:30:00.049"), Timestamp("2017-01-03 14:30:00.049"), Timestamp("2017-01-03 14:30:00.049")],
                   "x": [1,2,3]})
timestamp = df["timestamp"].values
timestamp = pd.to_datetime(timestamp)
timestamp = timestamp.tz_localize("UTC").tz_convert("US/Eastern") # Convert UTC to US/Eastern
timestamp = timestamp.tz_localize(None)  # Strip timezone information off.
df["timestamp"] = timestamp.values
df

输入:

              timestamp  x
2017-01-03 14:30:00.049  1
2017-01-03 14:30:00.049  2
2017-01-03 14:30:00.049  3

输出:

              timestamp  x
2017-01-03 09:30:00.049  1
2017-01-03 09:30:00.049  2
2017-01-03 09:30:00.049  3

附加内容

如果这一列最初是Unix时间(以毫秒为单位),可以使用这个方法将其转换为datetime64[ns]格式的数组:

timestamp = pd.to_datetime(timestamp, unit="ms")
6

datetime的fromtimestamp其实是从一个POSIX时间戳开始的,也就是从1970年1月1日格林威治标准时间(GMT)起的毫秒数。

In [11]: datetime.datetime.fromtimestamp?
Type:        builtin_function_or_method
String form: <built-in method fromtimestamp of type object at 0x101d90500>
Docstring:   timestamp[, tz] -> tz's local time from POSIX timestamp.

In [12]: datetime.datetime.fromtimestamp(0)
Out[12]: datetime.datetime(1969, 12, 31, 16, 0)

In [13]: datetime.datetime.fromtimestamp(1)
Out[13]: datetime.datetime(1969, 12, 31, 16, 0, 1)

我觉得这可能是个问题,因为我在太平洋标准时间(PST)时区。

这和pandas的Timestamp不太一样(虽然在底层,它是从1970年1月1日开始的纳秒数)。

In [21]: pd.Timestamp(0)
Out[21]: Timestamp('1970-01-01 00:00:00')

要转换一个Timestamp/datetime64的列,可以使用tz_convert(如果它们是没有时区信息的,也就是tz naive,你需要先用tz_localize来添加时区信息):

In [31]: pd.Timestamp(0).tz_localize('UTC')
Out[31]: Timestamp('1970-01-01 00:00:00+0000', tz='UTC')

In [32]: t = pd.Timestamp(0).tz_localize('UTC')

In [33]: t.tz_convert('US/Eastern')
Out[33]: Timestamp('1969-12-31 19:00:00-0500', tz='US/Eastern')

请查看文档中的时区处理部分

40

只需要使用 tz_convert 方法就可以了。

假设你有一个时间戳对象:

   stamp = Timestamp('1/1/2014 16:20', tz='America/Sao_Paulo')
   new_stamp = stamp.tz_convert('US/Eastern')

如果你想转换日期范围:

   range = date_range('1/1/2014', '1/1/2015', freq='S', tz='America/Sao_Paulo')
   new_range = range.tz_convert('US/Eastern')

对于大规模的时间序列:

   import numpy as np
   ts = Series(np.random.randn(len(range)), range)
   new_ts = ts.tz_convert('US/Eastern')

正如另一个回答中提到的,如果你的数据没有设置时区,你需要先用 tz_localize 来设置时区:

   data.tz_localize('utc')

撰写回答