Di Ruby on Rails, bagaimana cara memformat tanggal dengan akhiran "th", seperti pada, "Sun 5 Oktober"?


177

Saya ingin menampilkan tanggal dalam format: hari pendek dalam seminggu, bulan pendek, hari dalam sebulan tanpa memimpin nol tetapi termasuk akhiran "th", "st", "nd", atau "rd".

Misalnya, hari pertanyaan ini ditanyakan akan menampilkan "Kamis 2 Oktober".

Saya menggunakan Ruby 1.8.7, dan Time.strftime sepertinya tidak melakukan ini. Saya lebih suka perpustakaan standar jika ada.


2
Anda mungkin ingin menggunakan kata "suffix" dalam pertanyaan atau judul Anda untuk mempermudah pencarian orang lain. Saya tidak yakin apakah ada kata lain untuk ini ketika berbicara tentang kencan.
— Harley Holcombe

Pertanyaan yang sangat bagus Saya memikirkan hal yang sama hanya beberapa hari yang lalu - sangat membantu.
— RichH

Jawaban:


278

Gunakan metode ordinalize dari 'active_support'.

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

Catatan, jika Anda menggunakan IRB dengan Ruby 2.0, Anda harus terlebih dahulu menjalankan:

require 'active_support/core_ext/integer/inflections'

15
Perhatikan saja ini tidak ada di perpustakaan standar.
— Chris Lloyd

97

Anda dapat menggunakan metode helper bantu ordinalalize active_support pada angka.

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

30

Mengambil jawaban Patrick McKenzie sedikit lebih jauh, Anda dapat membuat file baru di config/initializersdirektori Anda yang disebut date_format.rb(atau apa pun yang Anda inginkan) dan memasukkan ini ke dalamnya:

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

Kemudian dalam kode tampilan Anda, Anda dapat memformat tanggal apa pun hanya dengan menetapkannya sebagai format tanggal baru:

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

Sederhana, ini bekerja, dan mudah untuk dikembangkan. Cukup tambahkan lebih banyak baris format dalam file date_format.rb untuk masing-masing format tanggal yang berbeda. Ini adalah contoh yang lebih sempurna.

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
Jawaban bagus. Untuk Rails 3, ActiveSupport telah berubah sedikit, jadi yang berikut ini adalah yang setara:Time::DATE_FORMATS.merge!(:my_date => lambda { |time| time.strftime("%a, %b #{ActiveSupport::Inflector.ordinalize(time.day)}") })
— Sidane

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

Saya suka jawaban Bartosz, tapi hei, karena ini Rails yang sedang kita bicarakan, mari kita selangkah lebih maju dengan licik. (Sunting: Meskipun saya hanya akan monkeypatch metode berikut, ternyata ada cara yang lebih bersih.)

DateTimeinstance memiliki to_formatted_smetode yang disediakan oleh ActiveSupport, yang menggunakan simbol tunggal sebagai parameter dan, jika simbol itu dikenali sebagai format standar yang valid, mengembalikan sebuah String dengan pemformatan yang sesuai.

Simbol-simbol tersebut didefinisikan oleh Time::DATE_FORMATS, yang merupakan hash simbol untuk string baik untuk fungsi format standar ... atau 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

Tapi hei, jika Anda tidak bisa menolak kesempatan untuk melakukan monkeypatch, Anda selalu bisa memberikan antarmuka yang lebih bersih:

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

Buat %oformat Anda sendiri .

Inisialisasi

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 }

Pemakaian

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

Anda dapat menggunakan ini dengan Datedan DateTimejuga:

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

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

Tidak yakin apakah ini didokumentasikan. Sepertinya saya tidak dapat menemukan catatan apa pun tetapi kami menggunakannya di basis kode kami sehingga harus menemukannya di suatu tempat.
— Joshua Pinter

1
Saya tidak bisa menjalankan ini pada 2.6.3. Mungkin itu dalam versi Ruby yang lebih lama? Atau mungkin seseorang monyet ditambal Timedalam proyek Anda?
— kcdragon

2
@kcdragon Wow, Anda memang benar. Mencari basis kode dan menemukan bahwa teman lama saya Chuck Bergeron menambahkan inisialisasi ini hampir 7 tahun yang lalu. Apapun, saya masih menemukan ini sangat berguna jadi saya sudah memperbarui jawabannya dengan cara mengimplementasikannya seperti yang kita miliki di CNTRAL.
— Joshua Pinter

2

Meskipun Jonathan Tran memang mengatakan dia mencari hari yang disingkat dalam minggu pertama diikuti oleh bulan yang disingkat, saya pikir mungkin berguna bagi orang-orang yang berakhir di sini untuk mengetahui bahwa Rails memiliki dukungan out-of-the-box untuk lebih biasanya bulan panjang yang dapat digunakan, bilangan bulat hari ordinalized, diikuti oleh tahun, seperti pada June 1st, 2018.

Itu dapat dengan mudah dicapai dengan:

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

Atau:

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

Anda dapat tetap menggunakan contoh waktu jika ingin juga:

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

Anda dapat menemukan lebih banyak format dan konteks tentang cara membuat custom di Rails API docs .

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.