Timestamps look different - ruby-on-rails

In Rails, I find that timestamps in the console look different to the actual html view even when you have the same code. Unless I'm doing something really stupid:
>> article = News.first
=> #<News id: 1, title: "Testing", body: "yadda yadda", role_id: 1, created_at: "2009-04-12 05:33:07", updated_at: "2009-04-12 05:33:07">
>> article.created_at
=> Sun, 12 Apr 2009 05:33:07 UTC +00:00
>> article.created_at.to_date
=> Sun, 12 Apr 2009
And in the view:
<% for article in #news %>
<% #current_date = article.created_at.to_date %>
<% if #current_date != #date %>
<%= #current_date %>
<% #date = #current_date %>
<% end %>
The output will be:
2009-04-14
Why are the formats different?

In config/initializers/time_formats.rb, write:
Time::DATE_FORMATS[:article] = "%a, %d %B %Y"

<%= calls to_s on the Date object, which results in 2009-04-14 no matter where it's called:
>> Date.today
=> Tue, 14 Apr 2009
>> Date.today.to_s
=> "2009-04-14"
I really don't know what gets called when you don't use to_s.
UPDATE: Now I know. If you don't use to_s or an equivalent, irb calls inspect on the date object:
>> Date.today.inspect
=> "Tue, 14 Apr 2009"
UPDATE 2:
You can replace #current_date with #current_date.to_s (or #current_date.to_s(:format)) in your view. Format can be short, long, db, long_ordinal, rfc822 or number.
You can also define a default date format in your application locale.

Related

Comparing datetime in Rails always false

I'm trying to compare two dates of which both are datetime.
closed_at and updated_at (while updated_at is the one already created by rails)
This is my code:
<% if #task.closed_at == #task.updated_at %>
*Some stuff*
<% end %>
With closing a task it gets automatically updated.
irb(main):011:0> Task.first.closed_at
=> Fri, 07 Aug 2015 10:47:58 CEST +02:00
irb(main):012:0> Task.first.updated_at
=> Fri, 07 Aug 2015 10:47:58 CEST +02:00
irb(main):013:0> Task.first.closed_at == Task.first.updated_at
=> false
irb(main):014:0> Task.first.closed_at.to_datetime == Task.first.updated_at.to_datetime
=> false
I've read this two posts:
comparing datetime and time produces a false result
DateTime comparison fails in Rails
But neither the data type is different nor the time zone.
Environment:
ruby 2.2.2p95
rails 4.2.3
pg 0.18.2
This can happen because ruby Time makes comparison with fractions of seconds. So the "print" may look equal, but there is some time difference between both dates.
Try to use to_f method to see the difference between #task.closed_at and #task.updated_at. Pretty sure is this issue.
To solve your problem, just ignore the milliseconds part of dates:
<% if #task.closed_at.to_i == #task.updated_at.to_i %>
*Some stuff*
<% end %>
Try this little experiment with any model that has a created_at and updated_at in the console:
user = User.new
user.created_at = 'Fri, 07 Aug 2015 10:47:58 CEST +02:00'.to_datetime
user.updated_at = 'Fri, 07 Aug 2015 10:47:58 CEST +02:00'.to_datetime
user.created_at == user.updated_at
The last statement above returns true. So there has to be a difference in the time not visible when the time is displayed.
It happens because of the little difference (in milliseconds) between those 2 variables. There is one blog post regarding this issue:
http://railsware.com/blog/2014/04/01/time-comparison-in-ruby/
Basically, an easy fix would be to convert the time values to int:
<% if #task.closed_at.to_i == #task.updated_at.to_i %>
*Some stuff*
<% end %>

Translate date(weekday, month) in Rails

Now when I add something to my database it enter created_at parameter also. When I use it in my view, it looks like this:
Thursday, 11 Jun 2015 9:52 AM
And I use it as:
<%= #current_feed.created_at.strftime("%A, %d %b %Y %l:%M %p") %>
Can I translate month and weekdays? Or create dictionary for it?
Try this .......
date = Date.parse('Thursday, 11 Jun 2015 9:52 AM')
=> Thu, 11 Jun 2015
date.mon
=> 6
date.mday
=> 11
date.wday
=> 4
Hope this will work for you.
I guess you are asking about date translation. Have a look at this question.
You should use I18n.localize. Refer this document.
You can also have a look at this question, to know how to have months in locale.

Rails - using capitalize on a month name from l18n

I have a string like this in my view
<%= l event.start_date, format: :long %>
which outputs
18 aout 2013
I would like to capitalize the month name without touching the yaml file, and tried several options which failed miserably. Is it possible?
If you call capitalize it only takes the first character, so you may use titleize
<%=(l Date.today, format: :long) %>
=> "MiƩrcoles, 28 de agosto de 2013"
<%=(l Date.today, format: :long).titleize %>
=> "MiƩrcoles, 28 De Agosto De 2013"
Please note that all the words are turned to capital letter
Update
$ rails c
Loading development environment (Rails 4.0.0)
>> helper.l Date.today, format: :long
=> "September 02, 2013"
>> helper.l Time.now, format: :long
=> "September 02, 2013 22:56"

How do I format my created_at output correctly with I18n?

I am using this I18n file.
I am calling it in my view like this:
<td class="center"><%= l o.created_at %></td>
This is being outputted like this:
Mon, 22 May 2013 04:04:43 +0000
For starters, why is it displaying May 22, 2013 and not April 22?
When I do it in the console, I get this:
> o.created_at
=> Mon, 22 Apr 2013 04:04:43 UTC +00:00
I don't want it to display the time, or rather would prefer to just say something like:
Monday, April 22, 2013 # 4:04am
How do I do that?
You can add custom date/time formats to your translation file. To see what time-based substitutions are possible, consult a reference for strfime
formats:
default: ! '%Y-%m-%d'
long: ! '%B %d, %Y'
short: ! '%b %d'
custom: ! '%A, %M %B, %Y # %l:%M%P'
In your view, you'd make use as follows:
<%= l o.created_at, :format => :custom %>
You may need to get rid of blank entries in your en.yml file to correct your translation errors.

In Ruby on Rails, how do I format a date with the "th" suffix, as in, "Sun Oct 5th"?

I want to display dates in the format: short day of week, short month, day of month without leading zero but including "th", "st", "nd", or "rd" suffix.
For example, the day this question was asked would display "Thu Oct 2nd".
I'm using Ruby 1.8.7, and Time.strftime just doesn't seem to do this. I'd prefer a standard library if one exists.
Use the ordinalize method from 'active_support'.
>> time = Time.new
=> Fri Oct 03 01:24:48 +0100 2008
>> time.strftime("%a %b #{time.day.ordinalize}")
=> "Fri Oct 3rd"
Note, if you are using IRB with Ruby 2.0, you must first run:
require 'active_support/core_ext/integer/inflections'
You can use active_support's ordinalize helper method on numbers.
>> 3.ordinalize
=> "3rd"
>> 2.ordinalize
=> "2nd"
>> 1.ordinalize
=> "1st"
Taking Patrick McKenzie's answer just a bit further, you could create a new file in your config/initializers directory called date_format.rb (or whatever you want) and put this in it:
Time::DATE_FORMATS.merge!(
my_date: lambda { |time| time.strftime("%a, %b #{time.day.ordinalize}") }
)
Then in your view code you can format any date simply by assigning it your new date format:
My Date: <%= h some_date.to_s(:my_date) %>
It's simple, it works, and is easy to build on. Just add more format lines in the date_format.rb file for each of your different date formats. Here is a more fleshed out example.
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}") }
)
>> require 'activesupport'
=> []
>> t = Time.now
=> Thu Oct 02 17:28:37 -0700 2008
>> formatted = "#{t.strftime("%a %b")} #{t.day.ordinalize}"
=> "Thu Oct 2nd"
Although Jonathan Tran did say he was looking for the abbreviated day of the week first followed by the abbreviated month, I think it might be useful for people who end up here to know that Rails has out-of-the-box support for the more commonly usable long month, ordinalized day integer, followed by the year, as in June 1st, 2018.
It can be easily achieved with:
Time.current.to_date.to_s(:long_ordinal)
=> "January 26th, 2019"
Or:
Date.current.to_s(:long_ordinal)
=> "January 26th, 2019"
You can stick to a time instance if you wish as well:
Time.current.to_s(:long_ordinal)
=> "January 26th, 2019 04:21"
You can find more formats and context on how to create a custom one in the Rails API docs.
Create your own %o format.
Initializer
config/initializers/srtftime.rb
module StrftimeOrdinal
def self.included( base )
base.class_eval do
alias_method :old_strftime, :strftime
def strftime( format )
old_strftime format.gsub( "%o", day.ordinalize )
end
end
end
end
[ Time, Date, DateTime ].each{ |c| c.send :include, StrftimeOrdinal }
Usage
Time.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"
You can use this with Date and DateTime as well:
DateTime.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"
Date.new( 2018, 10, 2 ).strftime( "%a %b %o" )
=> "Tue Oct 2nd"
I like Bartosz's answer, but hey, since this is Rails we're talking about, let's take it one step up in devious. (Edit: Although I was going to just monkeypatch the following method, turns out there is a cleaner way.)
DateTime instances have a to_formatted_s method supplied by ActiveSupport, which takes a single symbol as a parameter and, if that symbol is recognized as a valid predefined format, returns a String with the appropriate formatting.
Those symbols are defined by Time::DATE_FORMATS, which is a hash of symbols to either strings for the standard formatting function... or 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
But hey, if you can't resist the opportunity to monkeypatch, you could always give that a cleaner interface:
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

Resources