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") |
使用
我个人更喜欢使用
1 2 | >> '22.09.1986 10:30'.in_time_zone('Central Time (US & Canada)') # => Mon, 22 Sep 1986 10:30:00 CDT -05:00 |
这会将字符串中的日期和时间解析为提供的时区。
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对象中可接受的格式,然后再次解析它。
这就是我想出的方法。不是最漂亮的,但很管用。允许使用指定的格式分析字符串,然后将其转换为我知道的
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') |
我使用的默认格式是
以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") |