Day name with I18n - ruby-on-rails

Without translation, this would get me today's day name:
Date.today.strftime("%A")
How would I localize it?
I.e. "Mardi" if I18n.locale is set to fr.

You probably have in your locale file(s) the following:
# example with fr
fr:
date:
day_names: [Dimanche, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi]
# ^^^^^^^^ a week starts with a Sunday, not a Monday
In order to get today's name, you could do:
week_day = Date.today.wday # Returns the day of week (0-6, Sunday is zero)
I18n.t('date.day_names')[week_day]
or eventually
I18n.l(Date.today, format: '%A')

l Date.today, format: "%A"
Will work if you have the day_names in your translation file.

if you use rails-i18n, you will have the day names and month names already translated, e.g.:
I18n.l(value, format: "le %A %e %B à %-Hh%M")
# le Dimanche 19 Juillet à 21h00

Related

Displaying the date pattern string in Rails i18n localization

I'd like to get the template string of the localized date format in Rails. What I'm going for:
date_in_us = get_date_string(:en) # 'mm/dd/yyyy'
date_in_gb = get_date_string(:en-gb) # 'dd/mm/yyyy'
So to be clear I'm not trying to localize a real date, I'm trying to get the date format string so I could display it as a placeholder in a text field.
Everything I've searched for on the internet keeps bringing me back to actually localizing a date. :-/
That won't work because that's not how the format is specified. For English, this is how the date formats are specified:
formats:
default: "%Y-%m-%d"
long: "%B %d, %Y"
short: "%b %d"
Here are the docs for these percent placeholders in case you're curious.
To solve your problem, I'd create a date, localize it, and replace the parts:
date = Date.new(2000, 12, 31)
I18n.l(date).sub('2000', 'yyyy').sub('12', 'mm').sub('31', 'dd')
# => "yyyy-mm-dd"
Note that this might not work if the locale uses a 2 digit year format. Let's try it for some locales (using the default from rails-i18n):
def get_date_string(locale = I18n.current)
date = Date.new(2000, 12, 31)
I18n.l(date, locale: locale)
.sub('2000', 'yyyy')
.sub('12', 'mm')
.sub('31', 'dd')
end
formats = %i[en en-US en-GB es de fr pt].map do |locale|
[locale, get_date_string(locale)]
end.to_h
formats will be:
{
:en=>"yyyy-mm-dd",
:"en-US"=>"mm-dd-yyyy",
:"en-GB"=>"dd-mm-yyyy",
:es=>"dd/mm/yyyy",
:de=>"dd.mm.yyyy",
:fr=>"dd/mm/yyyy",
:pt=>"dd/mm/yyyy"
}
By default all translations should be placed inside the config/locales directory, divided into files.
Below is a sample en.yml with date patterns.
en:
date:
formats:
default: "%Y-%m-%d"
short: "%b %d"
long: "%B %d, %Y"
So, all of the following equivalent lookups will return the :short date format "%b %d":
I18n.t 'date.formats.short'
I18n.t 'formats.short', scope: :date
I18n.t :short, scope: 'date.formats'
I18n.t :short, scope: [:date, :formats]
Please check this guide on how to i18n localization works in Ruby on Rails

Convert string to datetime ruby on rails

I know this is basic but I've been struggling for a few hours now and I can't seem to apply one of the many ways there are to convert a string to datetime so I can save it in the database in this format 2018-03-16 00:12:17.555372. Thanks ahead
This is the string output in the console.
params[:event][:start_date]
"03/28/2018 1:46 AM"
[EDIT] Following some leads I've come up with smething really dirty maybe someone can help refactor I'm supressing AM or PM because I don't know how to parse that I know it's awfull any help is appreciated!
if !params[:event][:start_date].empty?
start_date = params[:event][:start_date]
start_date = start_date.gsub(/[AMP]/, '').squish
a = start_date.split('/')
tmp = a[0]
a[0] = a[1]
a[1] = tmp
a = a.split(',').join('/')
start_date = Time.parse(a)
end
if !params[:event][:end_date].empty?
end_date = params[:event][:end_date]
end_date = end_date.gsub(/[AMP]/, '').squish
a = end_date.split('/')
tmp = a[0]
a[0] = a[1]
a[1] = tmp
a = a.split(',').join('/')
end_date = Time.parse(a)
end
You can use DateTime to parse the date from a specific format.
if the format you are looking to parse is "03/28/2018 1:46 AM" then you can do this.
date = DateTime.strptime('03/28/2018 1:46 AM', '%m/%d/%Y %I:%M %p')
# date to ISO 8601
puts date.to_time
# output: 2018-03-28 07:16:00 +0530
puts date.strftime("%m/%d/%Y")
# output: 03/28/2018
Date formats:
Date (Year, Month, Day):
%Y - Year with century (can be negative, 4 digits at least)
-0001, 0000, 1995, 2009, 14292, etc.
%m - Month of the year, zero-padded (01..12)
%_m blank-padded ( 1..12)
%-m no-padded (1..12)
%d - Day of the month, zero-padded (01..31)
%-d no-padded (1..31)
Time (Hour, Minute, Second, Subsecond):
%H - Hour of the day, 24-hour clock, zero-padded (00..23)
%k - Hour of the day, 24-hour clock, blank-padded ( 0..23)
%I - Hour of the day, 12-hour clock, zero-padded (01..12)
%l - Hour of the day, 12-hour clock, blank-padded ( 1..12)
%P - Meridian indicator, lowercase (``am'' or ``pm'')
%p - Meridian indicator, uppercase (``AM'' or ``PM'')
%M - Minute of the hour (00..59)
You can refer to all formats here.
You can parse it like so in ruby:
Parses the given representation of date and time, and creates a DateTime object. This method does not function as a validator.
DateTime.parse('2001-02-03T04:05:06+07:00')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.parse('20010203T040506+0700')
#=> #<DateTime: 2001-02-03T04:05:06+07:00 ...>
DateTime.parse('3rd Feb 2001 04:05:06 PM')
#=> #<DateTime: 2001-02-03T16:05:06+00:00 ...>
Not entirely sure if the string you supplied can be parsed, here is the link to the ruby docs on datetimes Docs

How to use locale structure for I18n.localize?

The provided locale structure in the I18n gem can look like the following:
de:
date:
abbr_day_names:
- So
- Mo
- Di
- Mi
- Do
- Fr
- Sa
But trying to output the day as described in the guides doesn't work, it seems like it looks for a format: in the locale aswell?
I18n.locale = :de
l(Date.current, format: :abbr_day_names)
"I18n::MissingTranslationData: translation missing: de.date.formats.abbr_day_names"
This is how you should do (french used):
date:
abbr_day_names: [Dim, Lun, Mar, Mer, Jeu, Ven, Sam]
abbr_month_names: [~, Jan, Fév, Mar, Avr, Mai, Jun, Jul, Août, Sep, Oct, Nov, Déc]
day_names: [Dimanche, Lundi, Mardi, Mercredi, Jeudi, Vendredi, Samedi]
formats:
day_month: "%b %d"
default: "%Y-%m-%d"
hour: "%H:%M"
long: "%A %d %B %Y"
long_month: "%d %B %Y"
month_abbr: "%d %b %Y"
So in date.abbr_day_names you define the abbreviated day names, same for date.abbr_months_names. Then you can set a custom format located in date.formats.name_of_your_format
In your view, you would use it this way:
l(Date.current, format: :long)
# OR
l(Date.current, format: :month_abbr)
# etc.
It works the same with datetime.formats and time.formats.
Here is an example of a common en-US.yml file for date/time formats: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en-US.yml
I can't find the full documentation about every wildcards usable in the i18n localization system. If somebody knows where to get it, your input will be greatly appreciated!

Format the date using Ruby on Rails

The flickr api provides a posted date as unix timestamp one: "The posted date is always passed around as a unix timestamp, which is an unsigned integer specifying the number of seconds since Jan 1st 1970 GMT."
For example, here is the date '1100897479'. How do I format it using Ruby on Rails?
Once you have parsed the timestamp string and have a time object (see other answers for details), you can use Time.to_formatted_s from Rails. It has several formats built in that you can specify with symbols.
Quote:
time = Time.now # => Thu Jan 18 06:10:17 CST 2007
time.to_formatted_s(:time) # => "06:10"
time.to_s(:time) # => "06:10"
time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
time.to_formatted_s(:number) # => "20070118061017"
time.to_formatted_s(:short) # => "18 Jan 06:10"
time.to_formatted_s(:long) # => "January 18, 2007 06:10"
time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
(Time.to_s is an alias)
You can also define your own formats - usually in an initializer (Thanks to Dave Newton for pointing this out). This is how it's done:
# config/initializers/time_formats.rb
Time::DATE_FORMATS[:month_and_year] = "%B %Y"
Time::DATE_FORMATS[:short_ordinal] = lambda { |time| time.strftime("%B #{time.day.ordinalize}") }
Here's my go at answering this,
so first you will need to convert the timestamp to an actual Ruby Date/Time. If you receive it just as a string or int from facebook, you will need to do something like this:
my_date = Time.at(timestamp_from_facebook.to_i)
OK, so now assuming you already have your date object...
to_formatted_s is a handy Ruby function that turns dates into formatted strings.
Here are some examples of its usage:
time = Time.now # => Thu Jan 18 06:10:17 CST 2007
time.to_formatted_s(:time) # => "06:10"
time.to_s(:time) # => "06:10"
time.to_formatted_s(:db) # => "2007-01-18 06:10:17"
time.to_formatted_s(:number) # => "20070118061017"
time.to_formatted_s(:short) # => "18 Jan 06:10"
time.to_formatted_s(:long) # => "January 18, 2007 06:10"
time.to_formatted_s(:long_ordinal) # => "January 18th, 2007 06:10"
time.to_formatted_s(:rfc822) # => "Thu, 18 Jan 2007 06:10:17 -0600"
As you can see: :db, :number, :short ... are custom date formats.
To add your own custom format, you can create this file: config/initializers/time_formats.rb and add your own formats there, for example here's one:
Date::DATE_FORMATS[:month_day_comma_year] = "%B %e, %Y" # January 28, 2015
Where :month_day_comma_year is your format's name (you can change this to anything you want), and where %B %e, %Y is unix date format.
Here's a quick cheatsheet on unix date syntax, so you can quickly setup your custom format:
From http://linux.die.net/man/3/strftime
%a - The abbreviated weekday name (``Sun'')
%A - The full weekday name (``Sunday'')
%b - The abbreviated month name (``Jan'')
%B - The full month name (``January'')
%c - The preferred local date and time representation
%d - Day of the month (01..31)
%e - Day of the month without leading 0 (1..31)
%g - Year in YY (00-99)
%H - Hour of the day, 24-hour clock (00..23)
%I - Hour of the day, 12-hour clock (01..12)
%j - Day of the year (001..366)
%m - Month of the year (01..12)
%M - Minute of the hour (00..59)
%p - Meridian indicator (``AM'' or ``PM'')
%S - Second of the minute (00..60)
%U - Week number of the current year,
starting with the first Sunday as the first
day of the first week (00..53)
%W - Week number of the current year,
starting with the first Monday as the first
day of the first week (00..53)
%w - Day of the week (Sunday is 0, 0..6)
%x - Preferred representation for the date alone, no time
%X - Preferred representation for the time alone, no date
%y - Year without a century (00..99)
%Y - Year with century
%Z - Time zone name
%% - Literal ``%'' character
t = Time.now
t.strftime("Printed on %m/%d/%Y") #=> "Printed on 04/09/2003"
t.strftime("at %I:%M%p") #=> "at 08:56AM"
Hope this helped you.
I've also made a github gist of this little guide, in case anyone prefers.
Easiest is to use strftime (docs).
If it's for use on the view side, better to wrap it in a helper, though.
#CMW's answer is bang on the money. I've added this answer as an example of how to configure an initializer so that both Date and Time objects get the formatting
config/initializers/time_formats.rb
date_formats = {
concise: '%d-%b-%Y' # 13-Jan-2014
}
Time::DATE_FORMATS.merge! date_formats
Date::DATE_FORMATS.merge! date_formats
Also the following two commands will iterate through all the DATE_FORMATS in your current environment, and display today's date and time in each format:
Date::DATE_FORMATS.keys.each{|k| puts [k,Date.today.to_formatted_s(k)].join(':- ')}
Time::DATE_FORMATS.keys.each{|k| puts [k,Time.now.to_formatted_s(k)].join(':- ')}
Have a look at localize, or l
eg:
l Time.at(1100897479)
First you will need to convert the timestamp to an actual Ruby Date/Time.
If you receive it just as a string or int from facebook, you will need to do something like this:
my_date = Time.at(timestamp_from_facebook.to_i)
Then to format it nicely in the view, you can just use to_s (for the default formatting):
<%= my_date.to_s %>
Note that if you don't put to_s, it will still be called by default if you use it in a view or in a string e.g. the following will also call to_s on the date:
<%= "Here is a date: #{my_date}" %>
or if you want the date formatted in a specific way (eg using "d/m/Y") - you can use strftime as outlined in the other answer.
Since the timestamps are seconds since the UNIX epoch, you can use DateTime.strptime ("string parse time") with the correct specifier:
Date.strptime('1100897479', '%s')
#=> #<Date: 2004-11-19 ((2453329j,0s,0n),+0s,2299161j)>
Date.strptime('1100897479', '%s').to_s
#=> "2004-11-19"
DateTime.strptime('1100897479', '%s')
#=> #<DateTime: 2004-11-19T20:51:19+00:00 ((2453329j,75079s,0n),+0s,2299161j)>
DateTime.strptime('1100897479', '%s').to_s
#=> "2004-11-19T20:51:19+00:00"
Note that you have to require 'date' for that to work, then you can call it either as Date.strptime (if you only care about the date) or DateTime.strptime (if you want date and time). If you need different formatting, you can call DateTime#strftime (look at strftime.net if you have a hard time with the format strings) on it or use one of the built-in methods like rfc822.

Rails: How to make Date strftime aware of the default locale?

I have my default locale set in the environment.rb as de (German).
I also see all the error messages in German, so the locale is picked up by the server. But when I try to print date with strftime like following:
some_date.strftime('%B, %y')
It prints in English (January, 11), and not the expected German (Januar, 11).
How can I print the date according to the default locale?
Use the l (alias for localize) method instead of raw strftime, like this:
l(date, format: '%B %d, in the year %Y')
See here for more information.
You can also define 'named' formats, a couple of them (short, long) are already predefined.
you can also make it shorter:
l(some_date, :format => '%d %B %Y')
In es.yml put:
es:
date:
formats:
default: "%d / %m / %Y"
In index.html.erb put:
<%= l somemodel.datefield %>

Resources