Подтвердить что ты не робот

Как я могу использовать даты в стиле США в Rails, используя Ruby 1.9?

Я нахожусь в США, и мы обычно форматируем даты как "месяц/день/год". Я пытаюсь убедиться, что мое приложение Rails, использующее Ruby 1.9, принимает этот формат везде и работает так, как это было в Ruby 1.8.

Я знаю, что у многих людей есть эта проблема, поэтому я хотел бы создать окончательное руководство здесь.

В частности:

  • '04/01/2011 '- 1 апреля 2011 года, а не 4 января 2011 года.
  • '4/1/2011' также является 1 апреля 2011 года - ведущие нули не должны быть необходимы.

Как я могу это сделать?

Вот что я до сих пор.

Контроль даты # to_s поведение

У меня есть эта строка в application.rb:

    # Format our dates like "12/25/2011'
    Date::DATE_FORMATS[:default] = '%m/%d/%Y'

Это гарантирует, что если я сделаю следующее:

d = Date.new(2011,4,1)
d.to_s

... Я получаю "04/01/2011", а не "2011-04-01".

Управление строкой # to_date поведение

В настоящее время метод ActiveSupport String#to_date выглядит следующим образом (источник):

 def to_date
    return nil if self.blank?
    ::Date.new(*::Date._parse(self, false).values_at(:year, :mon, :mday))
  end

(В случае, если вы этого не сделаете, вторая строка создаст новую дату, пройдя год, месяц и день в этом порядке. То, как она получает значения года, месяца и дня, используется Date._parse, который анализирует строку и каким-то образом решает, что это за значения, а затем возвращает хэш. .values_at извлекает значения из этого хеша в порядке Date.new хочет их.)

Так как я знаю, что обычно буду проходить в строках типа "04/01/2011" или "4/1/2011", я могу исправить это путем monkeypatching его следующим образом:

class String

  # Keep a pointer to ActiveSupport String#to_date
  alias_method :old_to_date, :to_date

  # Redefine it as follows
  def to_date
    return nil if self.blank?
    begin
      # Start by assuming the values are in this order, separated by /
      month, day, year = self.split('/').map(&:to_i)
      ::Date.new(year, month, day)
    rescue
      # If this fails - like for "April 4, 2011" - fall back to original behavior
      begin
      old_to_date
      rescue NoMethodError => e
        # Stupid, unhelpful error from the bowels of Ruby date-parsing code
        if e.message == "undefined method `<' for nil:NilClass"
          raise InvalidDateError.new("#{self} is not a valid date")
        else
          raise e
        end
      end
    end
  end
end

class InvalidDateError < StandardError; end;

Это решение заставляет мои тесты проходить, но это безумие? Я просто пропускаю параметр конфигурации где-нибудь или есть другое, более простое решение?

Существуют ли какие-либо другие случаи синтаксиса даты, которые я не закрываю?

4b9b3361

Ответ 1

Gem: ruby-american_date

Этот камень был создан, так как я задал этот вопрос. Я сейчас использую его и был доволен.

https://github.com/jeremyevans/ruby-american_date

Ответ 2

Date.strptime - это, вероятно, то, что вы ищете в ruby ​​1.9.

Вы, вероятно, застряли в monkeypatching его на string.to_date, но strptime - лучшее решение для синтаксического анализа дат из строк в ruby ​​1.9.

Также, насколько мне известно, форматы симметричны с strftime.

Ответ 3

вы можете использовать rails-i18n gem или просто скопировать en-US.yml и установите стандартную локаль "ru-US" в config/application.rb

Ответ 4

Для разбора дат в стиле США вы можете использовать:

Date.strptime(date_string, '%m/%d/%Y')

В консоли:

> Date.strptime('04/01/2011', '%m/%d/%Y')
 => Fri, 01 Apr 2011 
> Date.strptime('4/1/2011', '%m/%d/%Y')
 => Fri, 01 Apr 2011 

Ответ 5

Использовать REE?: D

Серьезно, хотя. Если это небольшое приложение, которое вы полностью контролируете или стандартизируете в этом формате даты, исправление обезьян для проекта вполне разумно. Вам просто нужно убедиться, что все ваши входы поступают с правильным форматом, будь то через API или веб-сайт.

Ответ 6

Вместо использования to_s для экземпляров Date, привыкнуть использовать strftime. Он принимает строку формата, которая дает вам полный контроль над форматом даты.

Изменить: strptime дает вам полный контроль над синтаксическим анализом, указав также строку формата. Вы можете использовать одну и ту же строку формата в обоих методах.

Ответ 7

Другой вариант - Chronic - http://chronic.rubyforge.org/

Вам просто нужно установить префикс endian для форматирования только формата даты MM/DD/YYYY:

Chronic::DEFAULT_OPTIONS[ :endian_precedence ] = [ :middle ]

Однако значение по умолчанию для Chronic - это формат даты, не соответствующий порядковым номерам США!