Rails应用中如何为tzinfo gem添加自定义时区名称/偏移量?
解决tzinfo中自定义非整小时偏移Etc时区的问题
我来帮你搞定这个时区验证和偏移量获取的问题~针对你的需求,有两种可行的方案:
方案一:直接使用标准时区标识符(推荐)
tzinfo本身已经包含了像Indian/Delhi这类带非整小时偏移的标准时区,完全不需要自定义,直接调用就能用:
# 获取印度德里时区 delhi_tz = TZInfo::Timezone.get("Indian/Delhi") # 查看当前偏移量(UTC+5:30) puts delhi_tz.current_period.utc_offset / 3600.0 # 输出5.5
这个方案的好处是完全符合IANA时区标准,不需要额外维护自定义逻辑,而且如果未来该时区有规则变更(比如夏令时调整,虽然印度目前没有),tzinfo更新数据后会自动同步。
方案二:自定义Etc风格的非整小时偏移时区
如果你一定要使用Etc/GMT+5:30这类自定义标识符,可以通过注册自定义时区类的方式实现:
步骤1:创建自定义时区类
创建一个继承自TZInfo::OffsetTimezone的类(固定偏移时区,适合Etc这类无夏令时的场景):
class CustomEtcGMTPlus530 < TZInfo::OffsetTimezone def initialize # 注意:UTC偏移量的计算逻辑是「UTC时间 = 本地时间 + 偏移值」 # 对于UTC+5:30的时区,偏移值为 -(5*3600 + 30*60) = -19800 秒 super( "Etc/GMT+5:30", # 自定义的时区标识符 TZInfo::TimezoneOffset.new(-19800, 0, "GMT+5:30") # 偏移量、夏令时偏移、缩写 ) end end
步骤2:注册自定义时区
把这个类注册到tzinfo的数据源中,之后就能通过标识符获取:
# 注册自定义时区 TZInfo::TimezoneDataSourceFactory.get.data_source.register_timezone(CustomEtcGMTPlus530.new) # 现在可以正常获取了 custom_tz = TZInfo::Timezone.get("Etc/GMT+5:30") puts custom_tz.current_period.utc_offset / 3600.0 # 输出5.5
注意事项
- 自定义固定偏移时区不会处理夏令时规则,适合明确不需要夏令时的场景;
- IANA标准的Etc时区只有整小时偏移,所以tzinfo默认不支持带30分钟的版本,这也是你之前报错的原因。
内容的提问来源于stack exchange,提问作者Rick
相关产品推荐
相关产品推荐

