Ruby:strptime解析柏林时区出现时间偏移异常求助
问题:strptime解析欧洲IANA时区时出现时间偏移异常
现象复现
解析柏林时区时间时出现1小时偏移:
DateTime.strptime('2023-12-20 12:30 PM Europe/Berlin', '%Y-%m-%d %I:%M %p %Z').in_time_zone('Europe/Berlin') # => Wed, 20 Dec 2023 13:30:00.000000000 CET +01:00
解析美国中部时区则正常:
DateTime.strptime('2023-12-20 12:30 PM Central Time (US & Canada)', '%Y-%m-%d %I:%M %p %Z').in_time_zone('Central Time (US & Canada)') # => Wed, 20 Dec 2023 12:30:00.000000000 CST -06:00
原因分析
Ruby的strptime方法中,%Z指令仅支持解析缩写时区标识(如CET、CST),无法识别完整的IANA时区名称(如Europe/Berlin)。当传入Europe/Berlin时,strptime无法匹配到有效时区,会默认使用系统本地时区或UTC来解析时间字符串中的12:30 PM,之后调用in_time_zone转换到柏林时区时,就会因为初始解析时区错误出现偏移。
而Central Time (US & Canada)属于Ruby能识别的时区别名,会被映射到CST缩写,因此解析过程正常。
解决方案
方案1:直接用时区对象解析时间(推荐)
借助ActiveSupport::TimeZone的parse方法,直接指定时区解析时间字符串:
zone = ActiveSupport::TimeZone['Europe/Berlin'] zone.parse('2023-12-20 12:30 PM') # => Wed, 20 Dec 2023 12:30:00.000000000 CET +01:00
方案2:拆分时间与时区,分别处理
先提取时间部分和时区名称,解析时间后再绑定正确时区:
full_str = '2023-12-20 12:30 PM Europe/Berlin' time_part = full_str.split(' ')[0..2].join(' ') zone_str = full_str.split(' ').last # 解析时间后转换到目标时区 parsed_time = DateTime.strptime(time_part, '%Y-%m-%d %I:%M %p') ActiveSupport::TimeZone[zone_str].local_to_utc(parsed_time.to_time).in_time_zone(zone_str) # => Wed, 20 Dec 2023 12:30:00.000000000 CET +01:00
内容的提问来源于stack exchange,提问作者Eduardo Potter
相关产品推荐
相关产品推荐

