R语言中as.POSIXct处理夏令时不一致数据的行为解析请求
解释R中
as.POSIXct的夏令时相关行为 这事儿本质是夏令时(DST)切换搞的鬼,咱们一步步把它说清楚:
先还原你的代码和运行现象
ts <- c("2018-03-24 23:00:00", "2018-03-25 01:00:00", "2018-03-25 01:15:00", "2018-03-25 01:30:00", "2018-03-25 01:45:00", "2018-03-25 02:00:00") as.POSIXct(ts) # [1] "2018-03-24 CET" "2018-03-25 CET" "2018-03-25 CET" "2018-03-25 CET" "2018-03-25 CET" "2018-03-25 CET" as.POSIXct(ts[1:5]) # [1] "2018-03-24 23:00:00 CET" "2018-03-25 01:00:00 CET" "2018-03-25 01:15:00 CET" "2018-03-25 01:30:00 CET" "2018-03-25 01:45:00 CET" diff(as.POSIXct(ts)) # Time differences in hours # [1] 2.00 0.25 0.25 0.25 1.00 diff(as.POSIXct(ts[1:5])) # Time differences in hours # [1] 2.00 0.25 0.25 0.25
核心原因:中欧时区的夏令时切换
你的R会话默认用的是CET(中欧时间)时区,2018年3月25日凌晨2点是夏令时启动的时间点——时钟会直接从2:00跳到3:00,也就是说2018-03-25 02:00:00这个时间在CET时区是根本不存在的。
1. 为什么as.POSIXct的显示格式不一样?
当你转换整个ts向量时,因为包含了那个无效的2点时间,R会自动把它映射到夏令时生效后的有效时间2018-03-25 03:00:00。同时,R为了让输出格式统一,会简化所有时间的显示(只展示日期和时区),不再显示时分秒。
而当你只转换前5个元素(不含那个无效时间)时,所有时间都是合法的冬令时时间,R就会正常显示完整的时分秒信息。
2. 为什么diff()的最后结果不符合预期?
看diff(as.POSIXct(ts))的最后一个值是1.00小时,而不是你预期的0.25小时:
- 倒数第二个时间
2018-03-25 01:45:00 CET是冬令时,对应UTC时间是2018-03-25 00:45:00 - 最后那个无效的
2018-03-25 02:00:00被R自动转换为2018-03-25 03:00:00 CEST(夏令时,CEST比UTC快2小时),对应UTC时间是2018-03-25 01:00:00 - 两者的UTC时间差为1小时,这就是
diff结果显示1.00小时的原因——R会基于底层的UTC时间计算差值,而非表面的本地时间。
怎么避免这种问题?
最稳妥的方式是使用UTC时区处理时间(UTC没有夏令时切换,时间线完全连续):
# 指定UTC时区转换 as.POSIXct(ts, tz = "UTC") # 输出会保留完整时分秒: # [1] "2018-03-24 23:00:00 UTC" "2018-03-25 01:00:00 UTC" "2018-03-25 01:15:00 UTC" "2018-03-25 01:30:00 UTC" "2018-03-25 01:45:00 UTC" "2018-03-25 02:00:00 UTC" # 此时diff结果完全符合预期 diff(as.POSIXct(ts, tz = "UTC")) # Time differences in hours # [1] 2.00 0.25 0.25 0.25 0.25
内容的提问来源于stack exchange,提问作者lejon
相关产品推荐
相关产品推荐

