Rails ActiveSupport Time Parsing? - PullRequest
       14

Rails ActiveSupport Time Parsing?

30 голосов
/ 10 декабря 2008

Модуль ActiveSupport в Rails расширяет встроенный класс Time в ruby ​​несколькими методами.

Примечательно, что есть метод to_formatted_s, который позволяет писать Time.now.to_formatted_s(:db) для получения строки в формате базы данных, вместо того, чтобы писать везде ужасные строки strftime формата.

У меня вопрос, есть ли способ вернуться назад?

Что-то вроде Time.parse_formatted_s(:db), которое будет анализировать строку в формате базы данных, возвращая новый объект Time. Это похоже на то, что рельсы должны обеспечить, но если это так, я не могу найти это.

Я просто не могу его найти или мне нужно написать самому?

Спасибо

Ответы [ 5 ]

56 голосов
/ 25 сентября 2009

Похоже, ActiveSupport действительно предоставляет методы анализа, которые вы ищете (и я тоже искал), в конце концов! & Mdash; по крайней мере, если строка, которую вы пытаетесь проанализировать, является стандартной датой в формате ISO-8601 (:db format).

Если дата, которую вы пытаетесь проанализировать, уже находится в вашем местном часовом поясе, это действительно просто!

 > 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

Дополнительные ссылки на документацию для справки:

5 голосов
/ 05 августа 2010
ActiveSupport::TimeZone.new('UTC').parse('2009-09-23 09:18:08')
=> Wed, 23 Sep 2009 09:18:08 UTC +00:00
3 голосов
/ 07 февраля 2016

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
2 голосов
/ 18 мая 2012

Я только что столкнулся с этим, и ни один из приведенных выше ответов не был мне удовлетворительным В идеале можно использовать 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
1 голос
/ 25 сентября 2009
>> "2009-09-24".to_date
=> Thu, 24 Sep 2009
>> "9/24/2009".to_date
=> Thu, 24 Sep 2009

Прекрасно работает, если ваша дата не в каком-то странном формате.

...