RailsのActiveSupportモジュールは組み込みを拡張しますRuby Timeクラスに多数のメソッドがあります。
特に、_to_formatted_s
_メソッドがあります。このメソッドを使用すると、どこにでも醜いstrftime
形式文字列を記述する必要がなく、Time.now.to_formatted_s(:db)
を記述してデータベース形式の文字列を取得できます。
私の質問は、後退する方法はありますか?
Time.parse_formatted_s(:db)
のようなもので、データベース形式の文字列を解析し、新しいTimeオブジェクトを返します。これはRailsが提供する必要があるもののようですが、提供されている場合は見つかりません。
私はそれを見つけることができませんか、それとも自分で書く必要がありますか?
ありがとう
結局、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
参照用のその他のドキュメントリンク:
ActiveSupport::TimeZone.new('UTC').parse('2009-09-23 09:18:08')
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00
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
私もこれに遭遇し、上記の答えはどれも満足のいくものではありませんでした。理想的には、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
>> "2009-09-24".to_date
=> Thu, 24 Sep 2009
>> "9/24/2009".to_date
=> Thu, 24 Sep 2009
日付が奇妙な形式でない限り、うまく機能します。