31

Rails 的 ActiveSupport 模块用许多方法扩展了内置的 ruby​​ Time 类。

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

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

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

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

谢谢

4

5 回答 5

61

毕竟,看起来 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

更多文档链接供参考:

于 2009-09-24T21:24:27.000 回答
5
ActiveSupport::TimeZone.new('UTC').parse('2009-09-23 09:18:08')
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00
于 2010-08-05T16:17:58.093 回答
3

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
于 2016-02-07T06:36:47.767 回答
2

我也遇到了这个问题,以上答案都没有让我满意。理想情况下,可以使用ActiveSupport::TimeZonelike并以任意格式Time调用它并取回正确的对象。 不存在所以我创建了这个猴子补丁:.strptimeTimeZoneActiveSupport::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
于 2012-05-17T22:37:33.473 回答
1
>> "2009-09-24".to_date
=> Thu, 24 Sep 2009
>> "9/24/2009".to_date
=> Thu, 24 Sep 2009

除非您的日期采用某种奇怪的格式,否则效果很好。

于 2009-09-25T01:40:15.317 回答