如何在Ruby中格式化日期,以包含"rd",比如"3rd"。

26

我想格式化一个日期对象,以便显示类似于“7月3日”或“10月1日”的字符串。 我在 Date.strftime 中找不到生成“rd”和“st”的选项。 有人知道怎么做吗?

8个回答

41

如果你不使用Rails,则需要将以下ordinalize方法(从Rails源代码中无耻地抄袭)添加到Fixnum类中。

class Fixnum
  def ordinalize
    if (11..13).include?(self % 100)
      "#{self}th"
    else
      case self % 10
        when 1; "#{self}st"
        when 2; "#{self}nd"
        when 3; "#{self}rd"
        else    "#{self}th"
      end
    end
  end
end

那么请按照如下格式设置你的日期:

> now = Time.now
> puts now.strftime("#{now.day.ordinalize} of %B, %Y")
=> 4th of July, 2009

请注意,此答案有点过时。这是现在的样子,而这里是对Integer类的扩展 - Dennis

30
created_at.strftime("#{created_at.day.ordinalize} of %m, %y")

将会产生"2009年7月4日"


我必须在 { 前面添加 #,但这种方法运行得很好。谢谢! - xenon
你会如何给字符串变量排序?比如说,我需要将%m转换为序数。 - Batman
2
当你需要使用非典型的“7月4日”格式时,这很好,但如果你使用传统的“2009年7月4日”,就没有必要手动序数化:created_at.to_date.to_s(:long_ordinal) - Olivier Lacan

25

我会跟大家一样强烈建议你下载 activesupport gem, 然后将其作为一个库使用。你不需要安装整个 Rails 来使用ordinalize

% gem install activesupport
...
% irb 
irb> require 'rubygems'
#=>  true
irb> require 'activesupport'
#=>  true
irb> 3.ordinalize
#=>  "3rd"

2
好的观点。您还可以从facets(http://facets.rubyforge.org)库中获取此功能 - 需要'require'facets'或仅需'require'facets / integer / ordinal'即可获得此方法。 - Greg Campbell
我们如何仅提取序数?我想要做“3<span>th</span>”。 - Volte
Volte:3.ordinalize.sub(/\w+/, '<span>\0</span>') - rampion
2
有一个更简单的方法来获取你想要的日期而不需要手动操作天数整数: date.to_s(:long_ordinal)。详情请参见:http://api.rubyonrails.org/classes/Date.html#method-i-to_formatted_s - Olivier Lacan

8
我不认为Ruby有这个功能,但是如果你使用Rails,可以尝试以下方法:-
puts 3.ordinalize #=> "3rd"

它也可以在 Facets 中使用。 - Pesto

1

我不知道这是否比switch-case更快(或者有多大的差异),但是我创建了一个包含结尾的常量:

DAY_ENDINGS = ["th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th", "th", "st"]

然后就像这样使用它:
DAY_ENDINGS[date.mday]

我想把结尾放在一个

标签里。
<span>th</span>

1

需要 'activesupport' 库
1.ordinal => 'st'
1.ordinalize => '1st'


1

0
require 'time'

H = Hash.new do |_,k|
  k +
  case k
  when '1', '21', '31'
    'st'
  when '2', '22'
    'nd'
  when '3', '23'
    'rd'
  else
    'th'
  end
end 

def fmt_it(time)
  time.strftime("%A %-d, %-l:%M%P").sub(/\d+(?=,)/, H) 
end

fmt_it(Time.new)
  #=> "Wednesday 9th, 1:36pm"

fmt_it(Time.new + 3*24*60*60)
  #=> "Saturday 12th, 3:15pm"

我使用了String#sub的形式(也可以使用sub!),它将哈希表(H)作为其第二个参数。

sub使用的正则表达式是“匹配一个或多个数字,后跟逗号”。(?=,)是一个正向先行断言

我使用了Hash::new的形式创建了(空的)哈希表H,该形式需要一个块。这意味着如果H没有键k,则H[k]返回块计算出的值。在这种情况下,哈希表为空,因此块始终返回感兴趣的值。该块接受两个参数:哈希表(这里是H)和正在评估的键。我用下划线表示前者,表示块不使用它。以下是一些示例:

H['1']  #=>  "1st" 
H['2']  #=>  "2nd" 
H['3']  #=>  "3rd" 
H['4']  #=>  "4th" 
H['9']  #=>  "9th" 
H['10'] #=> "10th" 
H['11'] #=> "11th" 
H['12'] #=> "12th" 
H['13'] #=> "13th" 
H['14'] #=> "14th" 
H['22'] #=> "22nd" 
H['24'] #=> "24th" 
H['31'] #=> "31st" 

查看 Time#strftime 以获取格式化指令。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接