2008-12-09 28 views
30

Rails' ActiveSupport module extends the builtin ruby Time class with a number of methods.Rails的ActiveSupport时间解析?

值得注意的是,有to_formatted_s方法,它可以让你写Time.now.to_formatted_s(:db)得到一个字符串的数据库格式,而不是到处写丑strftime格式化字符串。

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

Time.parse_formatted_s(:db)这样会解析数据库格式的字符串,返回一个新的Time对象。这看起来像铁轨应该提供的东西,但如果是这样,我找不到它。

我只是无法找到它,或者我需要自己写吗?

感谢

回答

55

它看起来像的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,但我能够解决该问题,首先使用Da teTime.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 

看起来它甚至可以分析其他格式,如时间#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 

更多参考文档链接:

+0

感谢您发布如此多的细节。您的DateTime.strptime()引用对于需要从数据库中解析出ActiveRecord :: Base.connection.select_value()以字符串形式返回的日期的情况非常有用。 – Lee 2009-11-02 21:06:38

+0

凶手回答。我没有意识到Time.zone =“...”的工作。你为我节省了很多时间。 – rhh 2010-08-04 19:23:44

1
>> "2009-09-24".to_date 
=> Thu, 24 Sep 2009 
>> "9/24/2009".to_date 
=> Thu, 24 Sep 2009 

非常有用,除非你的日期格式很奇怪。

5
ActiveSupport::TimeZone.new('UTC').parse('2009-09-23 09:18:08') 
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00 
2

我刚刚遇到了这个问题,上面的答案都没有让我满意。理想情况下,人们可以使用ActiveSupport::TimeZone就像Time,并以任意格式调用.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 
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