I want to format a date object so that I can display strings such as "3rd July" or "1st October". I can't find an option in Date.strftime to generate the "rd" and "st". Any one know how to do this?
I'm going to echo everyone else, but I'll just encourage you to download the activesupport
gem, so you can just use it as a library. You don't need all of Rails to use ordinalize
.
% gem install activesupport ... % irb irb> require 'rubygems' #=> true irb> require 'activesupport' #=> true irb> 3.ordinalize #=> "3rd"
3<span>th</span>
–
Islander 3.ordinalize.sub(/\w+/, '<span>\0</span>')
–
Breakage date.to_s(:long_ordinal)
. See: api.rubyonrails.org/classes/Date.html#method-i-to_formatted_s –
Maculation Unless you're using Rails, add this ordinalize method (code shamelessly lifted from the Rails source) to the Fixnum class
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
Then format your date like this:
> now = Time.now
> puts now.strftime("#{now.day.ordinalize} of %B, %Y")
=> 4th of July, 2009
Integer
class. –
Endodontics created_at.strftime("#{created_at.day.ordinalize} of %m, %y")
Will produce "4th of July, 2009"
created_at.to_date.to_s(:long_ordinal)
. –
Maculation I'm going to echo everyone else, but I'll just encourage you to download the activesupport
gem, so you can just use it as a library. You don't need all of Rails to use ordinalize
.
% gem install activesupport ... % irb irb> require 'rubygems' #=> true irb> require 'activesupport' #=> true irb> 3.ordinalize #=> "3rd"
3<span>th</span>
–
Islander 3.ordinalize.sub(/\w+/, '<span>\0</span>')
–
Breakage date.to_s(:long_ordinal)
. See: api.rubyonrails.org/classes/Date.html#method-i-to_formatted_s –
Maculation I don't think Ruby has it, but if you have Rails, try this:-
puts 3.ordinalize #=> "3rd"
Seems I'm revisiting this topic for a third time, so I've updated my gist with some extra comments / usage.
https://gist.github.com/alterisian/4154152
Cheers, Ian.
I don't know if it makes it that much (any?) faster than switch-case, but I made a constant with the endings:
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"]
Then just used it like:
DAY_ENDINGS[date.mday]
As I wanted the ending inside a
<span>th</span>
require 'activesupport'
1.ordinal => 'st'
1.ordinalize => '1st'
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"
I have used the form of String#sub (one could use sub!
) that takes a hash (H
) as its second argument.
The regular expression used by sub
reads "match one or more digits followed by a comma". (?=,)
is a positive lookahead.
I created the (empty) hash H
using the form of Hash::new that takes a block. This simply means that if H
does not have a key k
, H[k]
returns the value computed by the block. In this case the hash is empty so the block always returns the value of interest. The block takes two arguments, the hash (here H
) and the key being evaluated. I've represented the former with an underscore, signalling that it is not used by the block). Some examples:
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"
See Time#strftime for formatting directives.
© 2022 - 2024 — McMap. All rights reserved.