188

我想以以下格式显示日期:一周中的短日期、短月份、不带前导零但包括“th”、“st”、“nd”或“rd”后缀的月份中的某天。

例如,询问此问题的日期将显示“Thu Oct 2nd”。

我正在使用 Ruby 1.8.7,而Time.strftime似乎并没有这样做。如果存在,我更喜欢标准库。

4

7 回答 7

292

使用“active_support”中的 ordinalize 方法。

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

注意,如果你在 Ruby 2.0 中使用 IRB,你必须首先运行:

require 'active_support/core_ext/integer/inflections'
于 2008-10-03T00:25:37.660 回答
107

您可以对数字使用 active_support 的 ordinalize 辅助方法。

>> 3.ordinalize
=> "3rd"
>> 2.ordinalize
=> "2nd"
>> 1.ordinalize
=> "1st"
于 2008-10-03T00:21:31.430 回答
32

进一步了解 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}") }
)
于 2009-01-11T16:10:30.970 回答
10
>> require 'activesupport'
=> []
>> t = Time.now
=> Thu Oct 02 17:28:37 -0700 2008
>> formatted = "#{t.strftime("%a %b")} #{t.day.ordinalize}"
=> "Thu Oct 2nd"
于 2008-10-03T00:29:53.640 回答
6

我喜欢 Bartosz 的回答,但是,嘿,既然这是我们正在谈论的 Rails,让我们在迂回中更上一层楼。(编辑:虽然我打算只对以下方法进行monkeypatch,但事实证明有一种更清洁的方法。)

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

这些符号由 定义Time::DATE_FORMATS,它是标准格式化函数的字符串的符号哈希...或 procs。哇哈哈。

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
于 2008-10-03T01:37:38.347 回答
6

创建自己的%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"
于 2018-10-20T14:52:10.527 回答
6

尽管 Jonathan Tran 确实说过他首先要查找缩写的星期几,然后是缩写的月份,但我认为对于最终来到这里的人来说,了解 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 文档中找到更多关于如何创建自定义格式和上下文的信息。

于 2019-01-26T04:25:58.963 回答