В Ruby on Rails, как мне отформатировать дату с суффиксом th, как в «Sun Oct 5th»?

174

Я хочу отображать даты в формате: короткий день недели, короткий месяц, день месяца без начального нуля, но включая суффикс "th", "st", "nd" или "rd".

Например, в тот день, когда был задан этот вопрос, отобразится "Thu Oct 2nd".

Я использую Ruby 1.8.7, а Time.strftime просто не делает этого. Я бы предпочел стандартную библиотеку, если она существует.

  • 2
    Возможно, вы захотите использовать слово «суффикс» в своем вопросе или заголовке, чтобы его было легче найти другим людям. Я не уверен, есть ли другое слово для этого, говоря о датах.
  • 0
    Отличный вопрос. Я думал об этом только пару дней назад - очень полезно.
Теги:
date

7 ответов

252
Лучший ответ

Используйте метод ordinalize из 'active_support'.

>> time = Time.new
=> Fri Oct 03 01:24:48 +0100 2008
>> time.strftime("%a %b #{time.day.ordinalize}")
=> "Fri Oct 3rd"

Примечание. Если вы используете IRB с Ruby 2.0, вы должны сначала запустить:

require 'active_support/core_ext/integer/inflections'
  • 14
    Просто отметьте, что это не в стандартной библиотеке.
88

Вы можете использовать active_support упорядочить вспомогательный метод для чисел.

>> 3.ordinalize
=> "3rd"
>> 2.ordinalize
=> "2nd"
>> 1.ordinalize
=> "1st"
28

Взяв Patrick McKenzie еще немного, вы можете создать новый файл в своем каталоге config/initializers с именем date_format.rb (или как хотите) и поместить его в него:

Time::DATE_FORMATS.merge!(
  my_date: lambda { |time| time.strftime("%a, %b #{time.day.ordinalize}") }
)

Затем в вашем коде просмотра вы можете форматировать любую дату, просто назначив ему новый формат даты:

My Date: <%= h some_date.to_s(:my_date) %>

Это просто, он работает, и его легко построить. Просто добавьте больше строк формата в файл date_format.rb для каждого из ваших разных форматов даты. Вот более подробный пример.

Time::DATE_FORMATS.merge!(
   datetime_military: '%Y-%m-%d %H:%M',
   datetime:          '%Y-%m-%d %I:%M%P',
   time:              '%I:%M%P',
   time_military:     '%H:%M%P',
   datetime_short:    '%m/%d %I:%M',
   due_date: lambda { |time| time.strftime("%a, %b #{time.day.ordinalize}") }
)
  • 7
    Хороший ответ. Для Rails 3 ActiveSupport немного изменился, поэтому следующее является эквивалентом: Time::DATE_FORMATS.merge!(:my_date => lambda { |time| time.strftime("%a, %b #{ActiveSupport::Inflector.ordinalize(time.day)}") })
  • 1
    @ Сидан обновлен, чтобы отразить это.
9
>> require 'activesupport'
=> []
>> t = Time.now
=> Thu Oct 02 17:28:37 -0700 2008
>> formatted = "#{t.strftime("%a %b")} #{t.day.ordinalize}"
=> "Thu Oct 2nd"
6

Мне нравится ответ Бартоша, но, эй, поскольку это Rails, о котором мы говорим, позвольте ему сделать шаг вперед в коварном. (Edit: Хотя я собирался просто обезвредить следующий метод, оказывается, есть более чистый способ.)

DateTime экземпляры имеют метод to_formatted_s, предоставляемый ActiveSupport, который принимает один символ в качестве параметра и, если этот символ распознается как допустимый предопределенный формат, возвращает строку со соответствующим форматированием.

Эти символы определяются Time::DATE_FORMATS, который представляет собой хэш символов для строк для стандартной функции форматирования... или procs. Bwahaha.

d = DateTime.now #Examples were executed on October 3rd 2008
Time::DATE_FORMATS[:weekday_month_ordinal] = 
    lambda { |time| time.strftime("%a %b #{time.day.ordinalize}") }
d.to_formatted_s :weekday_month_ordinal #Fri Oct 3rd

Но эй, если вы не можете устоять перед возможностью monkeypatch, вы всегда можете дать этому более чистый интерфейс:

class DateTime

  Time::DATE_FORMATS[:weekday_month_ordinal] = 
      lambda { |time| time.strftime("%a %b #{time.day.ordinalize}") }

  def to_my_special_s
    to_formatted_s :weekday_month_ordinal
  end
end

DateTime.now.to_my_special_s  #Fri Oct 3rd
2

Используйте %o.

Time.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"

Осторожно: Вы не можете использовать это с DateTime:

DateTime.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct %o"

Но вы все равно должны использовать Time и это хорошая причина для переключения.

  • 0
    Не уверен, если это задокументировано. Кажется, я не могу найти ни одной записи об этом, но мы используем ее в нашей кодовой базе, поэтому, должно быть, где-то нашли ее.
0

Хотя Джонатан Тран сказал, что сначала он искал сокращенный день недели, за которым следует сокращенный месяц, я думаю, что людям, которые оказались здесь, было бы полезно узнать, что Rails имеет встроенную поддержку для более обычно используемый длинный месяц, ординализованное целое число дня, за которым следует год, как June 1st, 2018.

Это может быть легко достигнуто с помощью:

Time.current.to_date.to_s(:long_ordinal)
=> "January 26th, 2019"

Или же:

Date.current.to_s(:long_ordinal)
=> "January 26th, 2019"

Вы также можете придерживаться временного примера, если хотите:

Time.current.to_s(:long_ordinal)
=> "January 26th, 2019 04:21"

Вы можете найти больше форматов и контекста о том, как создать свой собственный документ в Rails API.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню