Я хочу отображать даты в формате: короткий день недели, короткий месяц, день месяца без нуля в начале, но с суффиксом «th», «st», «nd» или «rd».
Например, в день, когда был задан этот вопрос, будет отображаться «Чт, 2 октября».
Я использую Ruby 1.8.7, и Time.strftime, похоже, этого не делает. Я бы предпочел стандартную библиотеку, если она существует.
Отличный вопрос. Я думал о том же всего пару дней назад - очень полезно.





Вы можете использовать вспомогательный метод active_support ordinalize для чисел.
>> 3.ordinalize
=> "3rd"
>> 2.ordinalize
=> "2nd"
>> 1.ordinalize
=> "1st"
На дворе 2020 год, и такие вещи по-прежнему заставляют меня любить Rails.
Используйте метод 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'
Просто обратите внимание, что этого нет в стандартной библиотеке.
>> require 'activesupport'
=> []
>> t = Time.now
=> Thu Oct 02 17:28:37 -0700 2008
>> formatted = "#{t.strftime("%a %b")} #{t.day.ordinalize}"
=> "Thu Oct 2nd"
Мне нравится ответ Бартоша, но, раз уж мы говорим о Rails, давайте сделаем еще один шаг вперед. (Обновлено: хотя я собирался просто исправить следующий метод, оказалось, что есть более чистый способ.)
Экземпляры DateTime имеют метод to_formatted_s, предоставляемый ActiveSupport, который принимает один символ в качестве параметра и, если этот символ распознается как допустимый предопределенный формат, возвращает строку с соответствующим форматированием.
Эти символы определены Time::DATE_FORMATS, который представляет собой хэш символов для строк для стандартной функции форматирования ... или для процедур. Бвахаха.
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
Взяв ответ Патрика Маккензи немного дальше, вы можете создать новый файл в своем каталоге 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}") }
)
Хороший ответ. Для Rails 3 ActiveSupport немного изменился, поэтому следующий эквивалент: Time::DATE_FORMATS.merge!(:my_date => lambda { |time| time.strftime("%a, %b #{ActiveSupport::Inflector.ordinalize(time.day)}") })
%o.config/initializers/srtftime.rb
module StrftimeOrdinal
def self.included( base )
base.class_eval do
alias_method :old_strftime, :strftime
def strftime( format )
old_strftime format.gsub( "%o", day.ordinalize )
end
end
end
end
[ Time, Date, DateTime ].each{ |c| c.send :include, StrftimeOrdinal }
Time.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"
Вы также можете использовать это с Date и DateTime:
DateTime.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"
Date.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"
Не уверен, что это задокументировано. Кажется, я не могу найти никаких записей об этом, но мы используем это в нашей кодовой базе, поэтому, должно быть, где-то его нашли.
Я не могу заставить это работать на 2.6.3. Может, это было в более старой версии Ruby? А может кто-то обезьяна пропатчил Time в вашем проекте?
@kcdragon Вау, ты был абсолютно прав. Поискал в базе кода и обнаружил, что мой старый приятель Чак Бержерон добавил этот инициализатор почти 7 лет назад. Тем не менее, я все еще считаю это очень полезным, поэтому я обновил ответ, рассказав, как его реализовать, как в CNTRAL.
Эти комментарии веселые!
Хотя Джонатан Тран сказал, что сначала ищет сокращенный день недели, за которым следует сокращенный месяц, я думаю, что людям, которые в конечном итоге здесь окажутся, было бы полезно узнать, что в 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.
Возможно, вы захотите использовать слово «суффикс» в своем вопросе или заголовке, чтобы их было легче найти другим людям. Я не уверен, есть ли для этого другое слово, когда речь идет о свиданиях.