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

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

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

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

Ответ 1

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

Ответ 2

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

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

Ответ 3

Взяв 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}") }
)

Ответ 4

>> require 'activesupport'
=> []
>> t = Time.now
=> Thu Oct 02 17:28:37 -0700 2008
>> formatted = "#{t.strftime("%a %b")} #{t.day.ordinalize}"
=> "Thu Oct 2nd"

Ответ 5

Мне нравится ответ Бартоша, но, эй, поскольку это 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

Ответ 6

Создайте свой собственный формат %o.

Initializer

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 }

Usage

Usage
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"

Ответ 7

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