我一直在解析字符串,我有一个测试用例,它一直在给我带来问题。使用strptime解析日期/时间字符串时,不考虑夏令时。据我所知,这是一个错误。我找不到关于这个bug的任何文档。这是Rails控制台中的一个测试用例。这是ruby 1.9.3-p215和Rails 3.2.2。
1.9.3-p125 :049 > dt = DateTime.strptime("2012-04-15 10:00 Central Time (US & Canada)", "%Y-%m-%d %H:%M %Z")
=> Sun, 15 Apr 2012 10:00:00 -0600
1.9.3-p125 :050 > dt = DateTime.strptime("2012-04-15 10:00 Central Time (US & Canada)", "%Y-%m-%d %H:%M %Z").utc
=> Sun, 15 Apr 2012 16:00:00 +0000
1.9.3-p125 :051 > dt = DateTime.strptime("2012-04-15 10:00 Central Time (US & Canada)", "%Y-%m-%d %H:%M %Z").utc.in_time_zone("Central Time (US & Canada)")
=> Sun, 15 Apr 2012 11:00:00 CDT -05:00
正如你所看到的,我必须转换为utc然后回到时区才能正确解释DST,但是时间也会移动一小时,所以这不是我解析出的字符串。有人有这个错误的解决方法或更可靠的方法将日期+时间+时区可靠地解析到DateTime对象中,在该对象中正确表示夏令时吗?谢谢。
编辑: 好的,我找到了一个解决方法,虽然我不确定它有多强大。
以下是一个例子:
ActiveSupport::TimeZone["Central Time (US & Canada)"].parse "2012-04-15 10:00"
将日期/时间字符串解析为正确的时区。我不确定解析方法对于处理这个问题有多强大,所以我想看看是否有更好的解决方法,但到目前为止这是我的方法。
答案 0 :(得分:6)
这是一个令人沮丧的问题。您正在寻找的Rails方法是Time.zone.parse
。首先使用DateTime.strptime
来解析字符串,然后通过Time.zone.parse
运行它来设置区域。查看以下控制台输出:
> Time.zone
=> (GMT-06:00) Central Time (US & Canada)
> input_string = "10/12/12 00:00"
> input_format = "%m/%d/%y %H:%M"
> date_with_wrong_zone = DateTime.strptime(input_string, input_format)
=> Fri, 12 Oct 2012 00:00:00 +0000
> correct_date = Time.zone.parse(date_with_wrong_zone.strftime('%Y-%m-%d %H:%M:%S'))
=> Fri, 12 Oct 2012 00:00:00 CDT -05:00
请注意,即使Time.zone
的偏移量为-6(CST),最终结果的偏移量为-5(CDT)。
答案 1 :(得分:0)
好的,这是迄今为止我发现处理此问题的最佳方法。我在lib文件中创建了一个实用程序方法。
# Returns a DateTime object in the specified timezone
def self.parse_to_date(date_string, num_hours, timezone)
if timezone.is_a? String
timezone = ActiveSupport::TimeZone[timezone]
end
result = nil
#Chronic.time_class = timezone # Trying out chronic time zone support - so far it doesn't work
the_date = Chronic.parse date_string
if the_date
# Format the date into something that TimeZone can definitely parse
date_string = the_date.strftime("%Y-%m-%d")
result = timezone.parse(date_string) + num_hours.to_f.hours
end
result
end
请注意,我手动将时间加上时间,因为Chronic.parse不像我在解析时所喜欢的那样健壮 - 当没有添加尾随零时失败,例如,如8:0而不是8:00。
我希望这对某人有用。将日期/时间/时区字符串解析为有效日期似乎是一个非常常见的事情,但我无法找到任何将所有三个结合在一起的解析代码。