使用 ActiveSupport::TimeWithZone 将 UTC 转换为用户定义的时区

Convert UTC to User-Defined Time Zone with ActiveSupport::TimeWithZone

提问人:VegaStudios 提问时间:11/6/2023 更新时间:11/7/2023 访问量:70

问:

作为 Rake 任务的一部分,我需要将 UTC 时间转换为用户时区的等效时间。我想做的是更改午夜的 UTC 时间戳,并在用户的时区中重新创建时间戳为午夜。

转换 UTC 时间

Wed, 01 Mar 2017 00:00:00 UTC +00:00

遵守夏令时(春季/夏季)时为东部夏令时 (EDT)

Wed, 01 Mar 2017 04:00:00 UTC +00:00
zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
time = "Wed, 01 Mar 2017 00:00:00 UTC +00:00"
time.in_time_zone(zone)
=> Tue, 28 Feb 2017 19:00:00.000000000 EST -05:00

上面的内容仍将保存在数据库中,因为 Rails 会将所有时间戳转换回 UTC。但是,我需要得到,因为这是用户所在时区一天的真正开始。Wed, 01 Mar 2017 00:00:00 UTC +00:00Wed, 01 Mar 2017 04:00:00 UTC +00:00

Ruby-on-Rails Ruby 时区 active支持

评论

0赞 Stefan 11/6/2023
“这是用户所在时区一天的真正开始”——不完全是。3 月 1 日仍然是美国东部时间 (UTC−05:00)。夏令时 EDT (UTC−04:00) 从 2017 年 3 月 12 日开始。
0赞 VegaStudios 11/7/2023
@Stefan,感谢您指出这一点。这是我的一个错误,我将更新上面的例子。这一点仍然存在,我正在寻找一天的真正开始。下面看起来有一些很好的解决方案。

答:

1赞 spickermann 11/6/2023 #1

如果要将时间初始化为特定时区中的特定时间,则需要使用正确的 EST 或 EDT 区域标识符(或 )初始化时间。EST -05:00EDT -04:00

time = "Wed, 01 Mar 2017 00:00:00 EST -05:00"
time.in_time_zone('UTC')
#=> Wed, 01 Mar 2017 05:00:00.000000000 UTC +00:00

time = "Wed, 01 Mar 2017 00:00:00 EDT -04:00"
time.in_time_zone('UTC')
#=> Wed, 01 Mar 2017 04:00:00.000000000 UTC +00:00
2赞 Stefan 11/6/2023 #2

您可以通过 ActiveSupport::TimeZone#parse 解析相对于时区的字符串。只需确保省略任何时区说明符,例如“UTC +00:00”:

zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")

time = zone.parse("Wed, 01 Mar 2017 00:00:00")
#=> Wed, 01 Mar 2017 00:00:00.000000000 EST -05:00

time.utc
#=> 2017-03-01 05:00:00 UTC

最后一次调用 to 只是为了说明目的,Rails 将在保存到数据库时自动执行此转换。utctime

使用数字输入:

time = zone.local(2017, 3, 1)
#=> Wed, 01 Mar 2017 00:00:00.000000000 EST -05:00
0赞 Akeel Ahmed Qureshi 11/6/2023 #3
utc_time = "Wed, 01 Mar 2017 00:00:00 UTC +00:00"
zone = ActiveSupport::TimeZone.new("Eastern Time (US & Canada)")
usr_time = utc_time.in_time_zone(zone)
midnight_time = usr_time.beginning_of_day
utc_midnight_time = midnight_time.utc

现在,您可以将utc_midnight_time保存在数据库中。

如果您还想创建一个时间戳,并假设您有一个调度程序 型。然后你可以这样做, Scheduler.create(时间戳:utc_midnight_time) 并保存它。