【问题标题】:Rails daylight savings time not accounted for when using DateTime.strptime使用 DateTime.strptime 时不考虑 Rails 夏令时
【发布时间】:2012-04-11 05:43:03
【问题描述】:

我一直在解析字符串,我有一个测试用例给我带来了问题。使用 strptime 解析日期/时间字符串时,不考虑夏令时。据我所知,这是一个错误。我找不到有关此错误的任何文档。这是 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"  

这会将日期/时间字符串解析为正确的时区。我不确定 parse 方法在处理这个问题时有多稳健,所以我想看看是否有更好的解决方法,但这是我目前的方法。

【问题讨论】:

    标签: ruby-on-rails-3 date timezone


    【解决方案1】:

    这是一个令人沮丧的问题。您正在寻找的 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)。

    【讨论】:

      【解决方案2】:

      好的,这是迄今为止我发现的处理此问题的最佳方法。我在 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.
      我希望这对某人有用。将日期/时间/时区字符串解析为有效日期似乎是一件很常见的事情,但我找不到任何将这三者结合在一起的解析代码。

      【讨论】:

      • 您可以像这样为 Chronic 设置时区 Chronic.time_class= ActiveSupport::TimeZone['Mexico City']
      猜你喜欢
      • 1970-01-01
      • 2013-09-22
      • 2011-08-14
      • 2018-01-01
      • 2017-09-15
      • 2013-09-15
      • 2020-09-12
      • 2020-03-01
      • 2018-02-04
      相关资源
      最近更新 更多