Rails:如何将日期时间字符串解析为特定时区

Rails: How to parse date-time string into a specific time zone

我在Debian上使用的是Rails3.2和Ruby1.9.3。我有一个应用程序,它通过HTML表单以字符串的形式收集日期、时间和时区。像这样:

1
2
3
start_date:"04-15-2010",
start_time:"10:00:00",
timezone:"Central Time (US & Canada)"

我要做的是将这三个元素解析为一个日期,这个日期以UTC的形式保存到我的数据库中,在这种情况下,一旦开始时间在UTC时区内,它将增加7个小时。所以当它以UTC的形式出现在数据库中时,存储时间将是17:00,而不是接收到的中心时间。

我试过这样分析日期:

1
ActiveSupport::TimeZone[timezone].at DateTime.strptime("{ 2012-04-09 20:00:00 }","{ %Y-%m-%d %H:%M:%S }").to_i

但是,我不能用%z将时区合并到结果时间中。它要么没有解析,要么时间被解释为UTC而不是中心时间。所以我的问题是,如何在不更改实际存储日期/时间值的情况下将日期字符串强制到某个时区。我希望能够将字符串解析为一个日期/时间对象,该对象包含正确的时区,以便将来的时区转换是准确的。我找遍了,找不到办法。这很奇怪,因为对于从HTML表单输入的日期来说,这似乎是常见的事情。谢谢你的帮助。


试试这个:

1
2
3
zone ="Central Time (US & Canada)"  

ActiveSupport::TimeZone[zone].parse("2013-04-03 17:47:00")


使用String#in_time_zone(轨道4+)

我个人更喜欢使用String#in_time_zone

1
2
>> '22.09.1986 10:30'.in_time_zone('Central Time (US & Canada)')
# => Mon, 22 Sep 1986 10:30:00 CDT -05:00

这会将字符串中的日期和时间解析为提供的时区。


%Z是指定时区名称的正确方法。你试过以下方法了吗?

1
2
date_and_time = '%m-%d-%Y %H:%M:%S %Z'
DateTime.strptime("04-15-2010 10:00:00 Central Time (US & Canada)",date_and_time)


我终于找到了做这件事的肮脏但明确的方法。

首先,使用简单的ruby time.strptime分析字符串,如下所示:

1
time = Time.strptime('12 : 00 : PM', '%I : %M : %p')

这样可以得到解析的时间,但还没有到达正确的时区。为了解决这个问题,我们将时间转换为字符串形式,并使用标准的activesupport::timezone parse对其进行分析。

1
Time.zone.parse(time.to_s)

结果是ActiveSupport::TimeWithZone将我们的时间解析到正确的时区。

我们必须这样做的原因是ActiveSupport::TimeZone和ActiveSupport::TimeWithZone都不支持strptime方法。因此,我们必须使用没有时区信息的核心ruby strptime解析时间,将其转换为ActiveSupport对象中可接受的格式,然后再次解析它。


这就是我想出的方法。不是最漂亮的,但很管用。允许使用指定的格式分析字符串,然后将其转换为我知道的Time.zone.parse所需的格式。

1
2
3
4
5
6
class ActiveSupport::TimeZone
  def strptime(time, format='%m/%d/%Y')
    formatted = Time.strptime(time, format).strftime('%Y-%m-%d %T')
    parse(formatted)
  end
end

然后,您可以执行类似于另一个问题中提到的操作,但使用指定的格式:

1
2
zone ="Central Time (US & Canada)"  
ActiveSupport::TimeZone[zone].strptime('2013-04-03', '%Y-%m-%d')

或者,如果您已经设置了时区:

1
2
Time.zone ="Central Time (US & Canada)"
Time.zone.strptime('01/13/2006')

我使用的默认格式是%m/%d/%Y,因为大多数时候我的用户都是这样输入的。您可以根据自己的需要进行自定义,也可以使用默认格式DateTime使用,这被认为是iso8601(%FT%T%z)。


以UTC格式转换特定日期格式。

1
ActiveSupport::TimeZone['UTC'].parse(Time.strptime('01/24/2019T16:10:16',"%m/%d/%YT%H:%M:%S").asctime)


要让datetime获取日期字符串并在不更改日期字符串值的情况下附加一个非UTC的时区,请使用它,它很简单,不会在闰日中断:)

1
xx = DateTime.strptime("9/1/15 #{object.time_zone}","%m/%d/%Y %Z")