Як я відформатую дату в суфіксі "th", як у "Rub Oct on Rails", у Ruby on Rails?


177

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

Наприклад, у день, коли було задано це питання, відображатиметься "Чт 2 жовтня".

Я використовую Ruby 1.8.7, а Time.strearch , схоже, не робить цього. Я вважаю за краще стандартну бібліотеку, якщо така існує.


2
Можливо, ви хочете використовувати слово "суфікс" у своєму запитанні чи заголовку, щоб полегшити пошук інших людей. Я не впевнений, чи є інше слово для цього, коли ми говоримо про побачення.
Харлі Холкомб

Відмінне запитання. Я думав про те саме саме пару днів тому - дуже корисно.
RichH

Відповіді:


278

Скористайтеся методом ординалізації з "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'

15
Зауважте лише, що це не в стандартній бібліотеці.
Кріс Ллойд

97

Ви можете скористатися методом упорядкування помічників active_support на числах.

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

30

Отримавши відповідь Патріка Маккензі трохи далі, ви можете створити новий файл у своєму 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)}") })
Sidane


6

Мені подобається відповідь Бартоша, але ей, оскільки ми говоримо про це Рейки, давайте зробимо це на крок уперед. (Редагувати. Хоча я збирався просто провести наступний метод, але виявляється, що існує більш чистий спосіб.)

DateTimeекземпляри мають to_formatted_sметод, наданий ActiveSupport, який приймає один символ як параметр і, якщо цей символ розпізнається як допустимий заздалегідь визначений формат, повертає String з відповідним форматуванням.

Ці символи визначаються символом Time::DATE_FORMATS, який є хеш символів або для рядків для стандартної функції форматування ..., або для проектів. 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

Але ей, якщо ви не можете протистояти можливості маніпулювання, ви завжди можете дати цьому чистіший інтерфейс:

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

3

Створіть свою власну %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"

Не впевнений, чи це документально підтверджено. Я не можу знайти жодного запису про це, але ми використовуємо його в нашій кодовій базі, тому, мабуть, його десь знайшли.
Джошуа Пінтер

1
Я не в змозі змусити це працювати на 2.6.3. Може, це було в більш старій версії Ruby? А може, хтось мавпа зафіксував Timeу вашому проекті?
kcdragon

2
@kcdragon Нічого собі, ти був абсолютно правий. Шукав базу коду і виявив, що мій старий приятель Чак Бергерон додав цей ініціалізатор майже 7 років тому. Незважаючи на це, я все ще вважаю це дуже корисним, тому я оновив відповідь, як його реалізувати так, як у нас це є в CNTRAL.
Джошуа Пінтер

2

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

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.