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 方法?