如何在特定时区(最好是我的应用程序的默认时区,而不是 UTC)中创建新的 DateTime 对象?

Posted

技术标签:

【中文标题】如何在特定时区(最好是我的应用程序的默认时区,而不是 UTC)中创建新的 DateTime 对象?【英文标题】:How to create a new DateTime object in a specific time zone (preferably the default time zone of my app, not UTC)? 【发布时间】:2012-07-11 18:00:44 【问题描述】:

我在/config/application.rb 中设置了时区,我希望我的应用程序中生成的所有时间默认都在这个时区,但是当我创建一个新的DateTime 对象(使用.new)时,它在GMT 中创建它。我怎样才能让它在我的应用程序的时区中?

/config/application.rb

config.time_zone = 'Pacific Time (US & Canada)'

irb

irb> DateTime.now
=> Wed, 11 Jul 2012 19:04:56 -0700 

irb> mydate = DateTime.new(2012, 07, 11, 20, 10, 0)
=> Wed, 11 Jul 2012 20:10:00 +0000                    # GMT, but I want PDT

使用in_time_zone 不起作用,因为这只会将 GMT 时间转换为 PDT 时间,这是错误的时间:

irb> mydate.in_time_zone('Pacific Time (US & Canada)')
=> Wed, 11 Jul 2012 13:10:00 PDT -07:00               # wrong time (I want 20:10)

【问题讨论】:

【参考方案1】:

我在 ApplicationController 中执行以下操作以将时区设置为用户的时间。

我不确定这是否是你想要的。

class ApplicationController < ActionController::Base
  before_filter :set_timezone
  def set_timezone
    # current_user.time_zone #=> 'London'
    Time.zone = current_user.time_zone if current_user && current_user.time_zone
  end

end

【讨论】:

这不是我想要的,但感谢您的发帖。也许它对其他人有帮助。【参考方案2】:

您可以使用 ActiveSupport 的 TimeWithZone (Time.zone) 对象来创建和解析应用程序时区中的日期:

1.9.3p0 :001 > Time.zone.now
 => Wed, 11 Jul 2012 19:47:03 PDT -07:00 
1.9.3p0 :002 > Time.zone.parse('2012-07-11 21:00')
 => Wed, 11 Jul 2012 21:00:00 PDT -07:00 

【讨论】:

这真的很有帮助!但是,如果您想在与您在 config/application.rb 中设置的 config.time_zone= 不同的区域中创建时间怎么办? 我会使用类似'2012-07-11 21:00'.to_datetime.in_time_zone('Eastern Time (US &amp; Canada)') 这实际上不起作用。假设您想为东部时间上午 9 点创建一个区域时间。如果您执行 '2012-07-11 09:00'.to_datetime.in_time_zone('Eastern Time (US & Canada)'),则会返回错误的时间,因为它是从 UTC 转换而来的。如果你这样做 '2012-07-11 09:00 Eastern Time (US & Canada)'.to_datetime.in_time_zone('Eastern Time (US & Canada)') 这仍然行不通,因为 DateTime 在白天时很糟糕节省时间。最好完全避免 DateTime。有什么想法吗?【参考方案3】:

如果有的话,我通常只在实例化 Time.new 或 DateTime.new 时指定 utc_offset。

[1] pry(main)> Time.new(2013,01,06, 11, 25, 00) #no specified utc_offset defaults to system time
 => 2013-01-06 11:25:00 -0500
[2] pry(main)> Time.new(2013,01,06, 11, 25, 00, "+00:00") #UTC
 => 2013-01-06 11:25:00 +0000
[3] pry(main)> Time.new(2013,01,06, 11, 25, 00, "-08:00") #PST
 => 2013-01-06 11:25:00 -0800 

【讨论】:

【参考方案4】:

另一种不用字符串解析的方式:

irb> Time.zone.local(2012, 7, 11, 21)
=> Wed, 07 Nov 2012 21:00:00 PDT -07:00

【讨论】:

参数与DatTime.new 方法不同。 Time.zone.local 不接受 0 或 -1 作为参数,会给出参数超出范围错误。【参考方案5】:

这也可以在 DateTime 类中通过包含时区来实现。

2.5.1 :001 > require 'rails'
 => true
2.5.1 :002 > mydate = DateTime.new(2012, 07, 11, 20, 10, 0)
 => Wed, 11 Jul 2012 20:10:00 +0000
2.5.1 :003 > mydate = DateTime.new(2012, 07, 11, 20, 10, 0, "PST")
 => Wed, 11 Jul 2012 20:10:00 -0800

https://docs.ruby-lang.org/en/2.6.0/DateTime.html

2.6.0 :001 > DateTime.new(2012, 07, 11, 20, 10, 0, "-06")
 => Wed, 11 Jul 2012 20:10:00 -0600
2.6.0 :002 > DateTime.new(2012, 07, 11, 20, 10, 0, "-05")
 => Wed, 11 Jul 2012 20:10:00 -0500

【讨论】:

【参考方案6】:

如果您想在本地时区创建日期时间不同于设置为config.time_zone

la_date = ActiveSupport::TimeZone["America/Los_Angeles"].parse('2020-02-01')
DateTime.new(la_date.year, la_date.month, la_date.day, la_date.hour, la_date.min, la_date.sec, la_date.zone)

【讨论】:

如果不想解析,也可以使用local。例如。 ActiveSupport::TimeZone["America/Los_Angeles"].local(2020, 1, 1, 12, 0).to_datetime

以上是关于如何在特定时区(最好是我的应用程序的默认时区,而不是 UTC)中创建新的 DateTime 对象?的主要内容,如果未能解决你的问题,请参考以下文章

如何更改 asp.net 应用程序的时区

如何使用地理编码宝石获得时区?

如何在 django DRF 中处理时区而不重复自己太多?

获取一个国家的默认时区(通过 CultureInfo)

在特定时区的一天开始时获取时间对象

如何在 python 中最好地调整带有时区的时间戳?