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)
的东西,它会解析数据库格式的字符串,返回一个新的Time对象。这似乎是rails应该提供的东西,但如果是,我找不到它。
我只是无法找到它,或者我是否需要自己编写?
由于
答案 0 :(得分:56)
看起来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
更多文档链接供参考:
答案 1 :(得分:5)
ActiveSupport::TimeZone.new('UTC').parse('2009-09-23 09:18:08')
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00
答案 2 :(得分: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
答案 3 :(得分:2)
我也遇到了这个问题,上述答案都没有让我满意。理想情况下,可以像ActiveSupport::TimeZone
一样使用Time
并使用任意格式调用.strptime
并返回正确的TimeZone
对象。 ActiveSupport::TimeZone.strptime
不存在所以我创建了这个monkeypatch:
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
答案 4 :(得分:1)
>> "2009-09-24".to_date
=> Thu, 24 Sep 2009
>> "9/24/2009".to_date
=> Thu, 24 Sep 2009
除非你的日期有些奇怪,否则效果很好。