En Ruby on Rails, ¿cómo formateo una fecha con el sufijo "th", como en"Sun Oct 5th"?


Quiero mostrar las fechas en el formato: día corto de la semana, mes corto, día del mes sin cero inicial pero incluyendo el sufijo "th", "st", "nd" o "rd".

Por ejemplo, el día en que se hizo esta pregunta se mostrará "Jue Oct 2nd".

Estoy usando Ruby 1.8.7, y Time.strftime simplemente no parece hacer esto. Preferiría una biblioteca estándar si existe.

Author: Alan W. Smith, 2008-10-03

5 answers

Utilice el método ordinalize de 'active_support'.

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

Nota, si estás usando IRB con Ruby 2.0, primero debes ejecutar:

require 'active_support/core_ext/integer/inflections'
 262
Author: Bartosz Blimke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-09-21 16:57:57

Puede usar el método ordinalize helper de active_support en números.

>> 3.ordinalize
=> "3rd"
>> 2.ordinalize
=> "2nd"
>> 1.ordinalize
=> "1st"
 90
Author: mwilliams,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-09-01 23:08:27

Tomando la respuesta de Patrick McKenzie un poco más lejos, podrías crear un nuevo archivo en tu directorio config/initializers llamado date_format.rb (o lo que quieras) y poner esto en él:

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

Luego en su código de vista puede formatear cualquier fecha simplemente asignándole su nuevo formato de fecha:

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

Es simple, funciona y es fácil de construir. Simplemente agregue más líneas de formato en el date_format.archivo rb para cada uno de sus diferentes formatos de fecha. Aquí hay un ejemplo más detallado.

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}") }
)
 28
Author: Richard Hurt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-11-16 14:20:59
>> require 'activesupport'
=> []
>> t = Time.now
=> Thu Oct 02 17:28:37 -0700 2008
>> formatted = "#{t.strftime("%a %b")} #{t.day.ordinalize}"
=> "Thu Oct 2nd"
 9
Author: Jimmy Schementi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-03 00:29:53

Me gusta la respuesta de Bartosz, pero bueno, ya que estamos hablando de Rails, vamos a dar un paso más en devious. (Editar: A pesar de que iba a monkeypatch el siguiente método, resulta que hay una manera más limpia.)

DateTime las instancias tienen un método to_formatted_s proporcionado por ActiveSupport, que toma un solo símbolo como parámetro y, si ese símbolo se reconoce como un formato predefinido válido, devuelve una cadena con el formato apropiado.

Esos símbolos están definidos por Time::DATE_FORMATS, que es un hash de símbolos para cualquiera de las cadenas para la función de formato estándar... o procs. 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

Pero bueno, si no puedes resistir la oportunidad de monkeypatch, siempre puedes darle una interfaz más limpia:

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
 5
Author: Patrick McKenzie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-10-03 01:37:38