Rails ActiveSupport 时间解析?

Posted

技术标签:

【中文标题】Rails ActiveSupport 时间解析?【英文标题】:Rails ActiveSupport Time Parsing? 【发布时间】:2010-09-26 03:52:39 【问题描述】:

Rails' ActiveSupport module extends the builtin ruby Time class with a number of methods.

值得注意的是,有to_formatted_s 方法,它可以让您编写Time.now.to_formatted_s(:db) 来获取数据库格式的字符串,而不必到处编写难看的strftime 格式字符串。

我的问题是,有没有办法倒退?

类似于Time.parse_formatted_s(:db) 的东西会解析数据库格式的字符串,返回一个新的时间对象。这似乎是 rails 应该提供的东西,但如果是,我找不到它。

我只是找不到,还是我需要自己写?

谢谢

【问题讨论】:

【参考方案1】:

看起来 ActiveSupport 确实提供了您正在寻找的解析方法(我也在寻找),毕竟! — 至少如果您尝试解析的字符串是标准的 ISO-8601 格式(:db 格式)日期。

如果您尝试解析的日期已经在您当地的时区,那真的很容易!

 > Time.zone.parse('2009-09-24 08:28:43')
=> Thu, 24 Sep 2009 08:28:43 PDT -07:00

 > Time.zone.parse('2009-09-24 08:28:43').class
=> ActiveSupport::TimeWithZone

然后可以轻松地将时区感知时间转换为 UTC

 > Time.zone.parse('2009-09-24 08:28:43').utc
=> 2009-09-24 15:28:43 UTC

或到其他时区:

 > ActiveSupport::TimeZone.us_zones.map(&:name)
=> ["Hawaii", "Alaska", "Pacific Time (US & Canada)", "Arizona", "Mountain Time (US & Canada)", "Central Time (US & Canada)", "Eastern Time (US & Canada)", "Indiana (East)"]

 > Time.zone.parse('2009-09-24 08:28:43').utc.in_time_zone('Eastern Time (US & Canada)')
=> Thu, 24 Sep 2009 11:28:43 EDT -04:00

另一方面,如果您尝试解析的日期字符串是 UTC,则看起来没有任何方法可以将其直接解析为 TimeWithZone,但我能够首先使用 DateTime.strptime 解决这个问题...

如果您尝试解析的日期是 UTC,并且您希望它保持为 UTC,您可以使用:

 > DateTime.strptime('2009-09-24 08:28:43', '%Y-%m-%d %H:%M:%S').to_time
=> 2009-09-24 08:28:43 UTC

如果您尝试解析的日期是 UTC,并且您希望将其转换为您的默认时区,您可以使用:

 > DateTime.strptime('2009-09-24 08:28:43', '%Y-%m-%d %H:%M:%S').to_time.in_time_zone
=> Thu, 24 Sep 2009 01:28:43 PDT -07:00

它看起来甚至可以解析其他格式,例如 Time#to_s 产生的奇怪格式:

irb -> Time.zone.parse('Wed, 23 Sep 2009 02:18:08').to_s(:db)
    => "2009-09-23 09:18:08"

irb -> Time.zone.parse('Wed, 23 Sep 2009 02:18:08 EDT').to_s(:db)
    => "2009-09-23 06:18:08"

我印象深刻。

以下是来自 [http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html][1]:

的更多示例
  Time.zone = 'Eastern Time (US & Canada)'        # => 'Eastern Time (US & Canada)'
  Time.zone.local(2007, 2, 10, 15, 30, 45)        # => Sat, 10 Feb 2007 15:30:45 EST -05:00
  Time.zone.parse('2007-02-10 15:30:45')          # => Sat, 10 Feb 2007 15:30:45 EST -05:00
  Time.zone.at(1170361845)                        # => Sat, 10 Feb 2007 15:30:45 EST -05:00
  Time.zone.now                                   # => Sun, 18 May 2008 13:07:55 EDT -04:00
  Time.utc(2007, 2, 10, 20, 30, 45).in_time_zone  # => Sat, 10 Feb 2007 15:30:45 EST -05:00

更多文档链接供参考:

http://api.rubyonrails.org/classes/ActiveSupport/TimeWithZone.html http://api.rubyonrails.org/classes/ActiveSupport/TimeZone.html

【讨论】:

感谢您发布如此详细的信息。您的 DateTime.strptime() 参考对于我需要从数据库中解析出 ActiveRecord::Base.connection.select_value() 作为字符串返回的日期的情况非常有用。 杀手级答案。我没有意识到 Time.zone = "..." 有效。你刚刚为我节省了大量时间。 感谢您的回答!如果您不想更改全局 TZ,您可以使用 Time::use_zone,例如。要解析 UTC,请使用 Time.use_zone('UTC')Time.zone.parse '2012-11-01 13:37'。 感谢您的提示。我不知道 Time::use_zone!【参考方案2】:
>> "2009-09-24".to_date
=> Thu, 24 Sep 2009
>> "9/24/2009".to_date
=> Thu, 24 Sep 2009

除非你的日期是某种奇怪的格式,否则效果很好。

【讨论】:

“一些奇怪的格式” - 就像世界其他地方一样格式化的日期吗? :)【参考方案3】:
ActiveSupport::TimeZone.new('UTC').parse('2009-09-23 09:18:08')
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00

【讨论】:

【参考方案4】:

我也遇到了这个问题,以上答案都没有让我满意。理想情况下,可以像使用Time 一样使用ActiveSupport::TimeZone 并以任意格式调用.strptime 并取回正确的TimeZone 对象。 ActiveSupport::TimeZone.strptime 不存在所以我创建了这个猴子补丁:

 class ActiveSupport::TimeZone
    def strptime(str, fmt, now = self.now)
      date_parts = Date._strptime(str, fmt)
      return if date_parts.blank?
      time = Time.strptime(str, fmt, now) rescue DateTime.strptime(str, fmt, now)
      if date_parts[:offset].nil?
        ActiveSupport::TimeWithZone.new(nil, self, time)
      else
        time.in_time_zone(self)
      end
    end
  end

【讨论】:

【参考方案5】:

Rails 5 终于提供了strptime

value = '1999-12-31 14:00:00'
format = '%Y-%m-%d %H:%M:%S'
Time.zone.strptime(value, format)
# => Fri, 31 Dec 1999 14:00:00 HST -10:00

ActiveSupport::TimeZone.all.sample.strptime(value, format)
# => Fri, 31 Dec 1999 14:00:00 GST +04:00

【讨论】:

以上是关于Rails ActiveSupport 时间解析?的主要内容,如果未能解决你的问题,请参考以下文章

运行任何 rails cmnd 时找不到“activesupport”

带 ActiveSupport 的默认时区(不带 Rails)

rails 应用程序未启动,资产上的“ActiveSupport::Deprection”错误:预编译

Rails:我如何需要 ActiveSupport 的rescue_from 方法?

rails activesupport 通知 - 错误的数据库运行时值

Alpine Linux 上的 Rails ActiveSupport 时间和时区错误