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

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

Например, в день, когда был задан этот вопрос, будет отображаться «Чт, 2 октября».

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

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

Harley Holcombe 03.10.2008 04:16

Отличный вопрос. Я думал о том же всего пару дней назад - очень полезно.

RichH 03.10.2008 22:10
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
183
2
50 168
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

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

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

На дворе 2020 год, и такие вещи по-прежнему заставляют меня любить Rails.

Adrian Carr 19.09.2020 02:58
Ответ принят как подходящий

Используйте метод 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'

Просто обратите внимание, что этого нет в стандартной библиотеке.

Chris Lloyd 01.02.2011 14:34

>> 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)}") })

Sidane 05.02.2011 13:41

Создайте свой собственный формат %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"

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

Joshua Pinter 20.10.2018 17:54

Я не могу заставить это работать на 2.6.3. Может, это было в более старой версии Ruby? А может кто-то обезьяна пропатчил Time в вашем проекте?

kcdragon 30.08.2019 19:03

@kcdragon Вау, ты был абсолютно прав. Поискал в базе кода и обнаружил, что мой старый приятель Чак Бержерон добавил этот инициализатор почти 7 лет назад. Тем не менее, я все еще считаю это очень полезным, поэтому я обновил ответ, рассказав, как его реализовать, как в CNTRAL.

Joshua Pinter 06.09.2019 05:01

Эти комментарии веселые!

fatfrog 21.01.2021 21:29

Хотя Джонатан Тран сказал, что сначала ищет сокращенный день недели, за которым следует сокращенный месяц, я думаю, что людям, которые в конечном итоге здесь окажутся, было бы полезно узнать, что в 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.

Другие вопросы по теме