Pandas中欧/哥本哈根时区转UTC出现重复值的解决方案问询
问题:哥本哈根时区时间转UTC出现重复值
我有一个Pandas DataFrame,需要将其中的datetime列从Europe/Copenhagen时区转换为UTC,但转换后的UTC列始终出现重复值。问题出在2024-10-27的转换中,UTC列出现了重复的2024-10-27 01:00,而非正确时间。
问题背景:
- 输入数据包含
Date(起始时间为00:00)、position、resolution、ID和quantity列 - 单ID下每日对应23-25个position,resolution为小时级
- 通过函数将Date、resolution和position计算为带时区的datetime再转UTC,但遇到夏令时切换(2024-10-27哥本哈根从CEST切换到CET,时钟回拨1小时)时出现重复UTC值
复现代码如下:
import pytz import pandas as pd import numpy as np from datetime import datetime, timedelta # Set up date range from 25th October 2024 to 28th October 2024 date_range = pd.date_range(start="2024-10-25", end="2024-10-28", freq="D") # Initialize an empty list to collect data data = [] # Populate data for each date for date in date_range: # Set number of positions based on date if date == datetime(2024, 10, 27): positions = range(1, 26) # 25 positions on 27th October else: positions = range(1, 25) # 24 positions on other dates # Generate data entries for each position for pos in positions: data.append({ "Date": date, "position": pos, "ID": "A", "quantity": np.random.randint(1, 100), "resolution": 'PT1H' }) # Create DataFrame df = pd.DataFrame(data) copenhagen_tz = pytz.timezone('Europe/Copenhagen') df['Date'] = pd.to_datetime(df['Date'],utc=False) # Define a dictionary to map resolution text to timedelta values resolution_map = { 'PT1H': timedelta(hours=1), 'PT30M': timedelta(minutes=30), 'PT15M': timedelta(minutes=15), 'PT5M': timedelta(minutes=5) } # Calculate the exact datetime by applying the resolution offset def calculate_exact_date(row): base_time = row['Date'] offset = (row['position'] - 1) * resolution_map[row['resolution']] # Handle DST ambiguity by using `ambiguous=True` to interpret ambiguous times consistently exact_date = base_time + offset return copenhagen_tz.normalize(exact_date) # Convert 'Date' to datetime in UTC, then localize to Europe/Copenhagen df['Date'] = pd.to_datetime(df['Date']).dt.tz_localize('CET') df['Date_Local'] = df.apply(calculate_exact_date, axis=1) df['Date_UTC'] = pd.to_datetime(df['Date_Local']).dt.tz_convert('UTC')
解决方案
问题根源是2024-10-27欧洲夏令时切换:哥本哈根当地时间从02:00回拨到01:00,导致两个本地时间(01:00 CEST和01:00 CET)对应同一个UTC时间(01:00 UTC)。但你的数据中27日有25个position,对应25小时的偏移,实际需要覆盖切换后的完整时间区间,正确的做法是直接基于本地时区的基准时间计算,明确处理夏令时切换的歧义。
以下是修改后的代码,无需修改输入数据格式:
import pytz import pandas as pd import numpy as np from datetime import datetime, timedelta # 生成数据部分保持不变 date_range = pd.date_range(start="2024-10-25", end="2024-10-28", freq="D") data = [] for date in date_range: if date == datetime(2024, 10, 27): positions = range(1, 26) else: positions = range(1, 25) for pos in positions: data.append({ "Date": date, "position": pos, "ID": "A", "quantity": np.random.randint(1, 100), "resolution": 'PT1H' }) df = pd.DataFrame(data) copenhagen_tz = pytz.timezone('Europe/Copenhagen') df['Date'] = pd.to_datetime(df['Date']) resolution_map = { 'PT1H': timedelta(hours=1), 'PT30M': timedelta(minutes=30), 'PT15M': timedelta(minutes=15), 'PT5M': timedelta(minutes=5) } def calculate_exact_date(row): # 先将基准日期转为哥本哈根时区的00:00,自动处理夏令时 base_local = copenhagen_tz.localize(row['Date'], is_dst=None) offset = (row['position'] - 1) * resolution_map[row['resolution']] # 在本地时区上叠加偏移,normalize自动处理DST切换的时间调整 exact_local = copenhagen_tz.normalize(base_local + offset) return exact_local # 计算本地时间并转换为UTC df['Date_Local'] = df.apply(calculate_exact_date, axis=1) df['Date_UTC'] = df['Date_Local'].dt.tz_convert('UTC')
修改说明:
- 正确本地化基准时间:不再硬编码
CET时区,而是用copenhagen_tz.localize()让pytz自动识别日期对应的时区(夏令时/冬令时),避免时区缩写的局限性。 - 自动处理歧义时间:
copenhagen_tz.normalize()会在夏令时回拨时,将重复的本地时间(如01:00)自动映射为切换后的冬令时时间,确保每个本地时间对应唯一的UTC时间。 - 简化转换逻辑:直接使用已带时区的
Date_Local列转换UTC,无需重复调用pd.to_datetime()。
验证结果:
修改后,2024-10-27的Date_UTC列将包含从2024-10-26 23:00:00+00:00到2024-10-27 23:00:00+00:00的25个唯一UTC时间,不再出现重复值。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

