在Ruby on Rails中,如何格式化带有" th"后缀的日期,例如" Sun Oct 5th"?

时间:2020-03-06 15:03:25  来源:igfitidea点击:

我想以以下格式显示日期:周的短日,短的月,月中的日期,且不带前导零,但包括" th"," st"," nd"或者" rd"后缀。

例如,询问该问题的日期将显示" 10月2日星期四"。

我正在使用Ruby 1.8.7,而Time.strftime似乎没有执行此操作。我希望有一个标准库。

解决方案

我们可以对数字使用active_support的序数化帮助器方法。

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

使用'active_support'中的ordinalize方法。

>> 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'

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

我喜欢Bartosz的答案,但是,嘿,既然这是我们正在谈论的Rails,那么就让它迈开一步。 (编辑:尽管我只是简单地修补以下方法,但事实证明这是一种更干净的方法。)

" DateTime"实例具有ActiveSupport提供的" to_formatted_s"方法,该方法将单个符号作为参数,并且如果该符号被识别为有效的预定义格式,则返回具有适当格式的String。

这些符号由Time :: DATE_FORMATS定义,它是符号到标准格式设置函数或者proc字符串的哈希。哇哈哈哈

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

再接一点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}") }
)