Format unix timestamp to something readable - ruby-on-rails

I'm trying to parse some bits through the google analytics cookie parser, I have this:
:Time_of_first_visit__c => Time.new(#data.utma_hash.fetch(:initial_visit_at)).to_datetime.to_formatted_s(:long),
:Time_of_previous_visit__c => Time.new(#data.utma_hash.fetch(:previous_visit_at)).to_datetime.to_formatted_s(:long),
:Current_visit_time__c => Time.new(#data.utma_hash.fetch(:current_visit_at)).to_datetime.to_formatted_s(:long),
But it's rendered like this:
Time of first visit
January 01, 1375174064 00:00
Current visit time
January 01, 1375174064 00:00
Time of previous visit
January 01, 1375174064 00:00

try to remove to_formatted_s(:long) and use it as argument of I18n.l
example:
I18n.l Time.new(#data.utma_hash.fetch(:initial_visit_at)).to_datetime
Of course you need a specification of datetime formats in your language .yml file, but it should work with the default one you can find in the official guides

This was the code I went with in the end:
:Time_of_first_visit__c => Time.at(#data.utma_hash.fetch(:initial_visit_at).to_i + 1.hour).strftime("%B %e, %Y at %I:%M %p"),
:Time_of_previous_visit__c => Time.at(#data.utma_hash.fetch(:previous_visit_at).to_i + 1.hour).strftime("%B %e, %Y at %I:%M %p"),
:Current_visit_time__c => Time.at(#data.utma_hash.fetch(:current_visit_at).to_i + 1.hour).strftime("%B %e, %Y at %I:%M %p"),

Related

Human Readable Date in Rails

I am trying to have the current date displayed in a view within my rails app. I'd like the following format: Day of week, Month, Day, Year.
Currently I am using:
<%= Time.now.strftime("%B %d, %Y") %>
This displays everything but the day of the week. How do I add the day of the week?
%A gives the day of the week
Customize how you prefer it!
<%= Time.now.strftime("%B %d, %Y, %A") %>
You can get the the name of the day as follows:
Time.now.strftime("%B %d, %Y %a") # => "January 18, 2014 Sat"
Time.now.strftime("%B %d, %Y %A") # => "January 18, 2014 Saturday"
You can also get day names from numbers 0...7 using Date::DAYNAMES like this:
require 'date'
(0...7).each { |x| puts Date::DAYNAMES[x] }
# Sunday
# Monday
# Tuesday
# Wednesday
# Thursday
# Friday
# Saturday
# => 0...7
You can use %A to display the full name e.g. Monday or %a for an abbreviated name e.g. Mon:
Time.now.strftime("%A, %B %d %Y") # => "Sunday, January 19, 2014"
Time.now.strftime("%a, %B %d %Y") # => "Sun, January 19, 2014"
Refer to the docs for more info.
You can use the followings:
distance_of_time_in_words(from_time, to_time) or
time_ago_in_words(from_time)
For example:
<span class="posted">Posted on <%= time_ago_in_words(post.created_at) %> ago</span>

Strange I18n date output with rails

I've got a strange problem with date translations in my Ruby On Rails 3 application, and I really don't understand why...
Here are my en.yml and fr.yml :
fr:
date:
formats:
default: "%d/%m/%Y"
short: "%e %b"
long: "%e %B %Y"
time:
formats:
default: "%d %B %Y %H:%M:%S"
short: "%d %b %H:%M"
long: "%A %d %B %Y %H:%M"
am: 'am'
pm: 'pm'
en:
date:
formats:
default: "%Y-%m-%d"
long: "%B %d, %Y"
short: "%b %d"
time:
am: am
formats:
default: ! '%a, %d %b %Y %H:%M:%S %z'
long: ! '%B %d, %Y %H:%M'
short: ! '%d %b %H:%M'
pm: pm
This is not specific to a particuliar view, but for instance in one of my view :
<td><%=l job_application.created_at, :format => :default %></td>
I get those strange outputs :
With locale = :en
=> t, 30 o 2012 18:09:33 +0000
With locale = :fr
=> 30 o 2012 18:09:33
Where do these wrong "formats" come from ?
I'm using Rails 3.2.8 (with Postgresql / gem pg), and everything related to I18n works fine except for dates.
Thanks for any help !
I think I've finally figured this out, sorry for taking so long.
The Rails l helper just calls I18n.localize. If you trace through the I18n.localize code, you'll end up here:
format = format.to_s.gsub(/%[aAbBp]/) do |match|
case match
when '%a' then I18n.t(:"date.abbr_day_names", :locale => locale, :format => format)[object.wday]
when '%A' then I18n.t(:"date.day_names", :locale => locale, :format => format)[object.wday]
when '%b' then I18n.t(:"date.abbr_month_names", :locale => locale, :format => format)[object.mon]
when '%B' then I18n.t(:"date.month_names", :locale => locale, :format => format)[object.mon]
when '%p' then I18n.t(:"time.#{object.hour < 12 ? :am : :pm}", :locale => locale, :format => format) if object.respond_to? :hour
end
end
So the localize helper doesn't use strftime for the "stringy" parts of the date/time, it tries to do it by itself. Add the translations (as arrays in your YAML) for the month and day names as above and your localized dates and times should start working.
If you don't have those translation arrays in your YAML, then I18n.t(:"date.abbr_month_names") will give you strings like this:
"translation missing: en.date.abbr_month_names"
and then I18n.localize will end up doing silly things like this:
"translation missing: en.date.abbr_month_names"[10]
That will use String#[] instead of the expected Array#[] and you end up with random looking single character month and day names.
Where do these wrong "formats" come from ?
Because created_at is a DateTime, rails using time formats (not date).
https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en.yml#L195
time:
am: am
formats:
default: ! '%a, %d %b %Y %H:%M:%S %z'
Type in your console
I18n.t(:"date")
to check if you are getting the translations you defined in your translation .yml file.
Compare the structure with the standard EN locale
I18n.t(:"date", locale:'en')
That made me notice I was declaring the date: attribute twice in my .yml, and the first part was being overwritten by the second declaration.
You should get the abbr_month_names that you declared when calling
I18n.t(:"date.abbr_month_names")
These are the ones that will be used when calling %b.
If not, check your locale .yml file to make sure they are properly declared, and not being declared twice.
You may also call I18n.locale to check if the .yml file you are editing is the one being used by rails

How to handle a `datetime` value so to change it from `2012-04-27 00:00:00` to `27 april 2012`?

I am using Ruby on Rails v3.2.2 and I would like to display a data as-like <day_number> <month_name> <year_number>. That is, I have a datetime database table column and I would like to change its contained values, for example, from 2012-04-27 00:00:00 to 27 april 2012.
How can I make that?
The standard way is use rails localization.
model
I18n.l(datetime, :format => :short)
controller
I18n.l(datetime, :format => :long)
view
<%= l(datetime), :format => :custom %>
config/locales/en.yml
en:
time:
formats:
long: "%A %B %d %Y | %I:%M %p GMT"
short: "%d %B %Y, %H:%M GMT"
custom: "your custom format"
date:
formats:
short: "%d %B %Y"
long: "%A %B %d %Y"
custom: "your custom format"
In your case the format should be "%d %A %Y".
The benefit is if you want to change format you can do it in one place for all datetimes which you are using.
You can use the method
str_name.strftime("%d %A %Y")

Localize a whole sentense passing it a datetime

I googled around but didn't find an answer - even if I guess it isn't tricky!
I'd like to localize a sentense that icludes date and time parameter. I want to pass it a complete datetime.
de_txt.yml
de:
article:
will_be_published_at: 'Wartet auf Veröffentlichung am %a %e. %b %Y um %H:%M Uhr'
My function with d is out of the database, field type is datetime
(second line is the one of my problem)
def icon_article_will_be_published_at(d)
alt = t('article.will_be_published_at', d)
image_tag("#{root_url}images/famfamfam/icons/date_next.png", :title => alt, :alt => alt, :class => "icon")
end
more about d
d.inspect # => Sat, 03 Dec 2011 14:07:00 CET +01:00
I can't figure it out and would appreciate help.
For this, you will need the I18n#l method, not the translate method.
It's a bit tricky, because you need a separate time format in the translations file (de.yml). This is one way to do it (adjust as necessary):
In config/locales/de.yml:
de:
time:
formats:
article_published_at: 'Wartet auf Veröffentlichung am %a %e. %b %Y um %H:%M Uhr'
Testing it in the console:
I18n.locale = :de
I18n.l Time.now, :format => :article_published_at
I would propose the following:
Split what you want to do in 2 steps:
Define a special format :um as described in the Rails Guide to I18n
de:
article:
will_be_published_at: 'Wartet auf Veröffentlichung am %datetime'
time:
formats:
um: "%a %e. %b %Y um %H:%M Uhr"
Call it then in the following snippet:
time = l(d, :format => :um)
alt = t('article.will_be_published_at', :datetime => time)
I could not test it, but it should work.

Extra space in cucumber step when using to_s(:long)

I have a step that fails with the following...
expected #has_content?("July 4, 2009") to return true, got false
The problem, I think, is the extra space between "July" and "4". I am using published_on.to_s(:long) in both the step definition and the view, so I'm not entirely sure where the extra space is coming from.
Any ideas?
It's what happens when you try:
Date.civil(2010, 7, 4).strftime("%e") # => " 4"
And Rails uses %e in their :long format. The funny thing is that %e isn't documented.
I would adjust my step definition to match Ruby behavior if you don't care about the extra space (extra spaces won't show in HTML anyway). If you do care about it, squish it:
Date.civil(2010, 7, 4).to_s(:long).squish # => "July 4, 2010"
Squish is avaiable in Rails 3. If you're using Rails 2, you can use gsub:
Date.civil(2010, 7, 4).to_s(:long).gsub(/\s+/, " ") # => "July 4, 2010"
I ran into the same problem with my cucumber test today!
The problem (as iain pointed out) is that Date::DATE_FORMATS[:long] is "%B %e, %Y". The %e, according to ri strftime, yields a blank-padded day number:
%d - Day of the month, zero-padded (01..31)
%-d no-padded (1..31)
%e - Day of the month, blank-padded ( 1..31)
So by default, this is what I see in Rails 3.1.3:
> d = '2012-02-01'.to_date
=> Wed, 01 Feb 2012
> d.to_s(:long)
=> "February 1, 2012"
Strangely, Rails uses a different day format for the :long format of times (%d, which yields "01") as for dates (%e, which yields " 1"):
> d = '2012-02-01'.to_time
=> 2012-02-01 00:00:00 UTC
> d.to_s(:long)
=> "February 01, 2012 00:00"
> Time::DATE_FORMATS[:long]
=> "%B %d, %Y %H:%M"
> Date::DATE_FORMATS[:long]
=> "%B %e, %Y"
The solution then is to use "%-d" for the day in your format string instead of %e:
> Date::DATE_FORMATS[:long] = "%B %-d, %Y"
=> "%B %-d, %Y"
> d = '2012-02-01'.to_date
Wed, 01 Feb 2012
> d.to_s(:long)
=> "February 1, 2012"
You can just add this line to a new initializer, config/initializers/date_formats.rb:
Date::DATE_FORMATS[:long] = "%B %-d, %Y"
Please comment on https://github.com/rails/rails/pull/1994 if you would like to see this default changed in Rails.
For what it's worth, I would rather use the "%-d" fix (or even "%-e"! which gives the same results) than ".squish", which is Rails-specific, and not as portable (why not use the Ruby-native ".squeeze", or even ".squeeze(' ')" at that then, if you don't want to mess around with the date formats?).
Also, as an update: #iain mentions that '%e' isn't documented. For what it's worth, it is now! (although interestingly, not "%-e" specifically, which, if you do try it, is valid, and works!)

Resources