pandas如何去除日期列各类时区后缀并统一转换为UTC时间
处理pandas日期列多类型时区后缀转UTC标准时间方案
问题场景
DataFrame的日期列为字符串格式,末尾附带未知类型的时区后缀,包含三类常见形式:
- 数字偏移格式:如
(+01) - 标准时区缩写:如
(UTC) - 夏令时/区域时区缩写:如
(BST)
需要将所有日期统一转换为UTC时区的标准datetime类型。
初始样例数据构造代码:
import pandas as pd from dateutil import tz data = {'Name': ['Bob', 'Mary','Alice'], 'Age': [21, 19, 20], 'Date': ['2022-07-07 16:43 (+01)', '2022-07-07 16:43 (UTC)', '2022-07-07 16:43 (BST)']} data = pd.DataFrame(data, columns=['Name', 'Age', 'Date'])
核心处理逻辑
不要直接用正则删除所有时区后缀:不同后缀代表的UTC偏移量不同,直接删除会导致时间值计算错误。正确流程是先识别每个日期的时区偏移,将当地时间转换为对应UTC时间:
- 拆分字符串中的日期主体和括号内的时区标识
- 建立时区缩写到UTC偏移量的映射表,兼容数字偏移、缩写两类后缀
- 解析无时区信息的基础时间,绑定对应时区后统一转换为UTC时区
可直接运行的实现代码
# 1. 拆分日期主体和时区标识 data[['dt_raw', 'tz_str']] = data['Date'].str.extract(r'^(.*?)\s*\((.*?)\)$') # 2. 配置时区映射表,可根据实际业务中遇到的后缀持续扩充 tz_offset_map = { 'UTC': 0, 'GMT': 0, 'BST': 1, # 英国夏令时,UTC+1 'EST': -5, # 美国东部标准时间,UTC-5 'EDT': -4, # 美国东部夏令时,UTC-4 'CST': 8, # 中国标准时间,UTC+8,若数据为其他区域CST可自行调整 'PST': -8, # 太平洋标准时间,UTC-8 'PDT': -7 # 太平洋夏令时,UTC-7 } def get_tz_offset(tz_string): tz_string = tz_string.strip() # 直接识别正负数字格式的偏移量 if tz_string.startswith(('+', '-')): return int(tz_string) # 缩写格式查映射表,未匹配到的默认按UTC处理,可按需调整兜底逻辑 return tz_offset_map.get(tz_string, 0) data['tz_offset_hour'] = data['tz_str'].apply(get_tz_offset) # 3. 解析时间并统一转UTC data['naive_time'] = pd.to_datetime(data['dt_raw'], format='%Y-%m-%d %H:%M') # 给时间绑定对应本地时区 data['local_time'] = data.apply( lambda row: row['naive_time'].tz_localize(tz.tzoffset(None, row['tz_offset_hour'] * 3600)), axis=1 ) # 转换为UTC标准时间 data['utc_datetime'] = data['local_time'].dt.tz_convert('UTC')
处理结果
样例数据处理后得到的utc_datetime列即为统一的UTC时区datetime类型,结果如下:
| Name | Age | Date | utc_datetime |
|---|---|---|---|
| Bob | 21 | 2022-07-07 16:43 (+01) | 2022-07-07 15:43:00+00:00 |
| Mary | 19 | 2022-07-07 16:43 (UTC) | 2022-07-07 16:43:00+00:00 |
| Alice | 20 | 2022-07-07 16:43 (BST) | 2022-07-07 15:43:00+00:00 |
注意事项
- 时区缩写存在重名问题,比如
CST可对应中国标准时间、美国中部标准时间、古巴标准时间,需要结合自身数据的业务场景确认映射值 - 映射表需要根据实际数据中出现的时区后缀持续补充,兜底逻辑(未匹配到的时区默认按UTC处理)可根据业务容错要求调整
- 如果业务不需要严格的时间准确性,仅需要删除后缀保留字符串对应的时间值,可以直接用正则替换括号及内容:
data['Date'].str.replace(r'\s*\(.*?\)$', '', regex=True)再转datetime即可,但该方法会忽略时区偏移导致时间值和真实UTC时间不符
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

