31

Rails の ActiveSupport モジュールは、組み込みの ruby​​ Time クラスをいくつかのメソッドで拡張します。

特筆すべきは、データベース形式で文字列を取得するto_formatted_sように記述できるメソッドがあることです。Time.now.to_formatted_s(:db)strftime

私の質問は、逆行する方法はありますか?

Time.parse_formatted_s(:db)データベース形式の文字列を解析し、新しい Time オブジェクトを返すようなもの。これは Rails が提供すべきもののように思えますが、提供されている場合、私はそれを見つけることができません。

見つけられないだけですか、それとも自分で書く必要がありますか?

ありがとう

4

5 に答える 5

61

結局のところ、ActiveSupport はあなたが探している (そして私も探していた) 解析メソッドを提供しているようです! — 少なくとも、解析しようとしている文字列が標準の ISO-8601 形式 ( :dbformat) の日付である場合。

解析しようとしている日付が既にローカル タイム ゾーンにある場合は、非常に簡単です。

 > 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::TimeZone同じように使用し、任意の形式でそれを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 に答える