Ruby on Rails'te, bir tarihi “Sun” 5 Ekim'de olduğu gibi “th” son ekiyle nasıl biçimlendiririm?


178

Tarihleri ​​şu şekilde görüntülemek istiyorum: haftanın kısa günü, kısa ay, ayın başında sıfır olmadan ancak "th", "st", "nd" veya "rd" soneki dahil.

Örneğin, bu sorunun sorulduğu gün "2 Ekim Per."

Ruby 1.8.7 kullanıyorum ve Time.strftime bunu yapmıyor gibi görünüyor. Varsa standart bir kütüphaneyi tercih ederim.


2
Diğer kişiler için daha kolay bulunabilmesi için sorunuzda veya başlığınızda "sonek" kelimesini kullanmak isteyebilirsiniz. Tarihlerden bahsederken bunun için başka bir kelime olup olmadığından emin değilim.
Harley Holcombe

Mükemmel soru. Ben sadece birkaç gün önce aynı şeyi düşünüyordum - çok yararlı.
RichH

Yanıtlar:


278

'Active_support' öğesinden ordinalize yöntemini kullanın.

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

Ruby 2.0 ile IRB kullanıyorsanız, önce şunları çalıştırmanız gerekir:

require 'active_support/core_ext/integer/inflections'

15
Bunun standart kütüphanede olmadığını unutmayın.
Chris Lloyd

97

Active_support'un sıralı yardımcı yöntemini sayılar üzerinde kullanabilirsiniz.

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

30

Patrick McKenzie'nin cevabını biraz daha ileri götürerek config/initializersdizininizde yeni bir dosya oluşturabilir date_format.rb(veya istediğinizi) ve buna koyabilirsiniz:

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

Ardından görünüm kodunuzda, herhangi bir tarihi yeni tarih biçiminizi atayarak biçimlendirebilirsiniz:

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

Çok basit, işe yarıyor ve inşa edilmesi kolay. Farklı tarih biçimlerinizin her biri için date_format.rb dosyasına daha fazla biçim satırı eklemeniz yeterlidir. İşte daha etli bir örnek.

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
Güzel cevap. Rails 3 için, ActiveSupport biraz değişti, bu yüzden aşağıdakiler eşdeğerdir: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

Bartosz'un cevabını seviyorum, ama hey, bahsettiğimiz Rails olduğundan, haksız bir adım atalım. (Düzenleme: Ben sadece aşağıdaki yöntemi monkeypatch olacaktı, ancak daha temiz bir yolu olduğu ortaya çıkıyor.)

DateTimeörneklerde, to_formatted_sActiveSupport tarafından sağlanan ve parametre olarak tek bir sembol alan bir yöntem vardır ve bu sembol önceden tanımlanmış geçerli bir biçim olarak tanınırsa, uygun biçimlendirmeye sahip bir Dize döndürür.

Bu semboller Time::DATE_FORMATS, standart biçimlendirme işlevi ... veya procs için dizelerin sembollerinin bir karması olan ile tanımlanır . 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

Ama hey, maymunbalığı fırsatına karşı koyamazsan, her zaman daha temiz bir arayüz verebilirsin:

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

Kendi %obiçiminizi oluşturun .

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 }

kullanım

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

Bunu Dateve ile de kullanabilirsiniz 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"

Bunun belgelenip belgelenmediğinden emin değilim. Herhangi bir kayıt bulamıyorum ama biz kod üssünde kullanıyoruz bu yüzden bir yerde bulmuş olmalı.
Joshua Pinter

1
2.6.3 üzerinde çalışmasını sağlayamıyorum. Belki Ruby'nin daha eski bir versiyonuydu? Ya da belki biri Timeprojenize yamalı maymun ?
kcdragon

2
@kcdragon Vay be, kesinlikle haklıydın. Kod tabanında arama yaptı ve eski dostum Chuck Bergeron'un bu başlatıcıyı yaklaşık 7 yıl önce eklediğini buldu. Ne olursa olsun, bunu hala çok yararlı buluyorum, bu yüzden CNTRAL'de olduğu gibi nasıl uygulanacağına dair cevabı güncelledim.
Joshua Pinter

2

Jonathan Tran ilk önce kısaltılmış günü ve ardından kısaltılmış ayı aradığını söylemesine rağmen, burada Rails'in daha fazlası için hazır destek olduğunu bilmesi yararlı olabilir. yaygın olarak kullanılabilir uzun ay, sıralı gün tamsayı, ardından yıl, olduğu gibi June 1st, 2018.

Aşağıdakilerle kolayca elde edilebilir:

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

Veya:

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

İsterseniz bir zaman örneğine sadık kalabilirsiniz:

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

Rails API belgelerinde nasıl özel bir format oluşturulacağına ilişkin daha fazla biçim ve bağlam bulabilirsiniz .

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.