如何在 Ruby-on-Rails 中将日期转换为 UTC 中午时间,而不考虑时区?

问题描述 投票:0回答:1

我在 Ruby-on-Rails 中有一个 Date 实例。我想将其转换为 UTC 时间的中午。 我该怎么办?

我认为这会起作用。

date = Date.new(2024, 10, 20)
time = date.to_time + Time.now.gmt_offset + 3600*12
  # => 2024-10-20 12:00:00 +0100
time.utc
  # => 2024-10-20 11:00:00 UTC

我认为它确实有效,但似乎不再有效;它给出的是 UTC 11 点,而不是 12 点...考虑到 1 小时的差异,我怀疑这与我的机器位于英国时区这一事实有关。 但怎么会呢?

过去的很多文章和问答都提到了 Ruby 中的DateTime。但是,DateTime 在 Ruby 中已被弃用(例如,请参阅 2020 年的本文)。所以,我想要一个时间

在 Ruby 3 和 Rails 7 中实现这一目标的(最佳)方法是什么?

ruby-on-rails ruby date time
1个回答
0
投票

Rails(可能)最好的方法

开门见山,使用 Rails 将

Date
转换为 UTC 中午
Time
的最简单、最清晰的方法可能是这样:

date = Date.new(2024, 10, 20)
date.to_time(:utc) + 12.hours
  # => 2024-10-20 00:00:00 UTC

这里,Rails 中的

Date#to_time
可以选择接受
:local
(默认)或
:utc
官方参考)参数,与原生 Ruby 不同。 请注意,默认选项
:local
的意思是:

Ruby 的进程时区,即

ENV['TZ']
。如果需要应用程序的时区,请使用
in_time_zone
代替。


为什么OP的方法不起作用?

这里解释了为什么您的示例代码不起作用;这是因为

  1. 2024年10月20日仍处于英国夏令时(BST:+0100)时区
  2. Ruby 考虑系统时间的时区,Ruby 的
    Date#to_time
    似乎也考虑到了这一点,其中时区实际上取决于在夏季和冬季时间之间定期切换的地区的日期
  3. 因此,2024-10-20 使用
    Date#to_time
    转换为 BST(英国夏令时间)时区当天的 00:00。见下文:
    • Date.new(2024,10,20).to_time  # => 2024-10-20 00:00:00 +0100
      (夏令时)
    • Date.new(2024,10,28).to_time  # => 2024-10-28 00:00:00 +0000
      (GMT=UTC)
  4. 您可能在时钟更改为 GMT/UTC(现在是 2024 年 10 月 28 日)后执行了代码,因此
    Time.now.gmt_offset
    返回 0。
  5. 因此,您的代码片段中
    Date.new(2024, 10, 20)
    中与 UTC 的时间偏移现在未正确考虑,而当您在 BST 时区期间运行代码时却考虑到了。
根据您的方式,最快的解决方法是将

Time.now.gmt_offset

 的当前时间替换为当天的实际 
time

date = Date.new(2024, 10, 20) time = date.to_time (time + time.gmt_offset + 3600*12).utc # ← use "time" instead of Time.now # => 2024-10-20 12:00:00 UTC # or similarly, but only in Rails: (time + time.gmt_offset + 3600*12).in_time_zone("UTC") # in Rails only (time + time.gmt_offset + 12.hours).utc # in Rails only # => 2024-10-20 12:00:00 UTC
相关替代方式

以下是一些替代方法。

date = Date.new(2024, 10, 20) t = Time.new(date.year, date.mon, date.day, 12, in: "UTC") t = Time.new(*(date.strftime("%Y %m %d 12").split.map(&:to_i)), in: "UTC") t = Time.parse(date.strftime("%Y-%m-%d 12:00:00 UTC")) # => 2024-10-20 12:00:00 UTC # Rails only t = Time.use_zone("UTC") do midday = Time.zone.parse(date.to_s)+12.hours end # => <ActiveSupport::TimeWithZone> Sun, 20 Oct 2024 12:00:00.000000000 UTC +00:00
最后一个对 Time 使用两个 Rails 类方法(如

过去的答案中所建议):Time.use_zoneTime.zone(注意,有点令人困惑,本机 Ruby 有一个实例方法Time#zone

,它返回时区的字符串)。

© www.soinside.com 2019 - 2024. All rights reserved.