Ruby 时区——到 UTC 并返回

Posted

技术标签:

【中文标题】Ruby 时区——到 UTC 并返回【英文标题】:Ruby Timezones — to UTC and back 【发布时间】:2016-05-06 04:35:51 【问题描述】:

我运行一个计划站点,允许用户为其帐户设置时区。然后,他们可以在该时区的日历上安排“帖子”。在后端,我会花时间将其转换为 UTC 时间(工作人员在 UTC 时间处理并获取这些帖子)。

我在 Ruby(使用 Puma/Sinatra)上运行该网站,但没有使用 Rails,我想远离 Rails。前端有 html/ERB/JS,后端有 mysql

我认为简单地添加/减去 UTC 偏移量就可以解决所有问题。我有一个简单的列表,其中包含 TIMEZONE <--> UTCOFFSET,而且效果很好——至少我是这么认为的。

然后我意识到当给定的时区(或地点)当前处于 DST 时,这不起作用。

夏季的维也纳:UTC 偏移量:+2h

冬天的维也纳:UTC 时差:+1h

有没有一种简单的方法可以给 Ruby(不是 Rails)一个“时区 ID”并接收正确调整后的 UTC 偏移量?

喜欢:

user.timezone = "Europe/Vienna"
utc_adjusted_time = post.local_time.to_i + get_utc_offset(user.timezone)

get_utc_offset知道它是否在夏令时。有什么想法吗?

我浏览了 IANA 数据库(这绝对是矫枉过正),我在 Github 上搜索了许多 Gist,我尝试滥用 Rails 似乎拥有的任何东西,但没有走得很远。

你们是怎么处理这个问题的?理想情况下,如前所述,每个帖子都将被转换并保存到 DST 剥离的 UTC 时间。谢谢!

【问题讨论】:

get_utc_offset 需要知道它是否在 DST 本地时间。不是现在。基本上,您需要一个适当的时区类,例如api.rubyonrails.org/classes/ActiveSupport/TimeZone.html - 但这看起来像是来自 Rails。 (我不是 Ruby 人,所以可能对你可以使用的东西有一些幼稚的假设)。请注意,如果本地时间在 DST 转换前后,则本地到 UTC 的映射可能是不可能的或不明确的。 (例如,向前弹跳时,凌晨 1:30 可能根本不存在;回退时,凌晨 1:30 可能会出现两次)。你需要制定出你想要的行为。 您可能还需要考虑存储时区和本地时间,而不是 UTC,请记住规则可能会随着时间的推移而改变......到您安排的事件发生时,它可能不会如果您继续存储 UTC,则在用户最初指定的本地时间。 Offtopic:Ruby 1.6 发行说明包含来自 Matz 的提交评论:speakerdeck.com/skade/the-dark-side-of-matz-1?slide=11 @JonSkeet 奇怪的时间模棱两可的情况很可能是我愿意妥协的极端情况,暂时不支持(99.99% 的帖子都在工作时间内)——关于存储原始时间/时区——是的,我也这样做,只是没有提及。 github.com/panthomakos/timezone ,在我的应用程序中很好地使用了这个,运行得很好。希望这会有所帮助。 【参考方案1】:

只需使用 Ruby TZInfo gem。

您的用例与in the readme 显示的完全相同:

require 'tzinfo'

tz = TZInfo::Timezone.get('America/New_York')
local = tz.utc_to_local(Time.utc(2005,8,29,15,35,0))

utc = tz.local_to_utc(local)

period = tz.period_for_utc(Time.utc(2005,8,29,15,35,0))
id = period.zone_identifier

查看TZInfo::TimePeriod 的文档,您可以看到您询问的其他信息:

period.offset
period.dst?

...等等

仅供参考——Rails 时区支持无论如何都是基于这个 gem。然后 Rails 开始在顶部放置一些时髦的别名(我建议不要使用)。请参阅the timezone tag wiki 中有关 Rails 的部分。

【讨论】:

以上是关于Ruby 时区——到 UTC 并返回的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Ruby 中更改 DateTime 的时区?

python / pytz问题从本地时区转换为UTC然后返回

如何让 Ruby 解析时间,就好像它在不同的时区一样?

JSON如何反序列化日期时间并将UTC转换为指定时区?

将 UTC 设置为默认日期时区

如何在 execl() 函数中更改时区(TZ=UTC)输出。