Ruby and Rails "Date.today" format - ruby-on-rails

In IRB, if I run following commands:
require 'date'
Date.today
I get the following output:
=> #<Date: 2015-09-26 ((2457292j,0s,0n),+0s,2299161j)>
But in Rails console, if I run Date.today, I get this:
=> Sat, 26 Sep 2015
I looked at Rails' Date class but can't find how Rails' Date.today displays the output differently than Ruby's output.
Can anybody tell, in Rails how Date.today or Date.tomorrow formats the date to display nicely?

The answer to your question is ActiveSupport's core extension to Date class. It overrides the default implementations of inspect and to_s:
# Overrides the default inspect method with a human readable one, e.g., "Mon, 21 Feb 2005"
def readable_inspect
strftime('%a, %d %b %Y')
end
alias_method :default_inspect, :inspect
alias_method :inspect, :readable_inspect
Command line example:
ruby-2.2.0 › irb
>> require 'date'
=> true
>> Date.today
=> #<Date: 2015-09-27 ((2457293j,0s,0n),+0s,2299161j)>
>> require 'active_support/core_ext/date'
=> true
>> Date.today
=> Sun, 27 Sep 2015

Rails' strftime or to_s methods should do what you need.
For example, using to_s:
2.2.1 :004 > Date.today.to_s(:long)
=> "September 26, 2015"
2.2.1 :005 > Date.today.to_s(:short)
=> "26 Sep"

If you run this:
require 'date'
p Date.today.strftime("%a, %e %b %Y")
You'll get this: "Sat, 26 Sep 2015"

Related

What's wrong with Rails's Date

I ran into this non-sense problem this morning in Rails 3.2 console. I'm under MacOS 10.10, my timezone is +7.
Loading development environment (Rails 3.2.12)
irb(main):001:0> Date.today
=> Sun, 16 Nov 2014
irb(main):002:0> Date.yesterday
=> Fri, 14 Nov 2014
irb(main):003:0>
Everything is fine with original Ruby Date:
irb(main):006:0> Date.today
=> #<Date: 2014-11-16 ((2456978j,0s,0n),+0s,2299161j)>
irb(main):007:0> Date.today.prev_day
=> #<Date: 2014-11-15 ((2456977j,0s,0n),+0s,2299161j)>
irb(main):008:0>
From the bug report here: https://rails.lighthouseapp.com/projects/8994/tickets/6410#ticket-6410-8
This is a subtle one - Date.yesterday uses Date.current which will use the time zone whereas Date.today doesn't. If you set your time zone to one where it's tomorrow already (e.g. Europe/Berlin as I type this) then you can get Date.today == Date.yesterday:
Time.zone = "Europe/London"
=> "Europe/London"
Date.today == Date.yesterday
=> false
Time.zone = "Europe/Berlin"
=> "Europe/Berlin"
Date.today == Date.yesterday
=> true

Ruby parse time zone string FORMAT for DB

I am trying to parse a string that's hitting my api. The incoming string is
"2014-03-19T04:00:00.000Z"
I need it in the following format for my db sql to work:
"2014-03-19 00:00:00 -0400"
Right now, the solution I have come up with is
Time.zone.parse("2014-03-19T04:00:00.000Z").in_time_zone('America/New_York').to_s
This feels like an inelegant solution to me and I feel that there should be a more dynamic way of doing things without specifying the time zone name (it should be local by default). I just want to switch the formatting of the strings as they are supposed to be equivalent.
Thanks
Configure the time_zone in the application.rb file and use it as below:
# application.rb:
class Application < Rails::Application
config.time_zone = 'America/New_York'
end
Time.zone.parse("2014-03-19T04:00:00.000Z").to_s
# => "2014-03-19 00:00:00 -0400"
More examples of use
$ > Time.zone = "America/New_York"
# => "America/New_York"
$ > Time.zone
# => (GMT-05:00) America/New_York
$ > Time.zone.now
# => Sat, 22 Mar 2014 18:28:48 EDT -04:00
irb(main):008:0> Time.parse("2014-03-19T04:00:00.000Z").getlocal.strftime("%F %T %z")
=> "2014-03-19 04:00:00 +0000"
On a system in GMT+1:
irb(main):003:0> Time.parse("2014-03-19T04:00:00.000Z").getlocal.strftime("%F %T %z")
=> "2014-03-19 05:00:00 +0100"

How to change date format in rails

Is this normal that rails put something like this :
DateTime.now = 2013-07-28T16:21:13+02:00
Why this T is between date and time ? How can i remove it. In I18n i have default:
default: ! '%a, %d %b %Y %H:%M:%S %z'
In your IRB console, if you call puts variable, it will make an implicit call to the method to_s on the variable object:
1.9.3 > DateTime.now
# => Wed, 28 Aug 2013 10:39:30 -0400
1.9.3 > puts DateTime.now
2013-08-28T10:39:33-04:00
# => nil
1.9.3 > DateTime.now.to_s
# => "2013-08-28T10:39:37-04:00"
This is why you see a "T" in the output, its .to_s's fault!

Is Time.zone.now.to_date equivalent to Date.today?

Is Time.zone.now.to_date equivalent to Date.today?
Another way to put it: will Time.zone.now.to_date == Date.today always be true?
If not, what's the best way to get a Date object corresponding to "now" in the application time zone?
They are not always the same. Time.zone.now.to_date will use the applications time zone, while Date.today will use the servers time zone. So if the two lie on different dates then they will be different. An example from my console:
ruby-1.9.2-p290 :036 > Time.zone = "Sydney"
=> "Sydney"
ruby-1.9.2-p290 :037 > Time.zone.now.to_date
=> Wed, 21 Sep 2011
ruby-1.9.2-p290 :038 > Date.today
=> Tue, 20 Sep 2011
Even easier: Time.zone.today
I also wrote a little helper method Date.today_in_zone that makes it really easy to get a "today" Date for a specific time zone without having to change Time.zone:
# Defaults to using Time.zone
> Date.today_in_zone
=> Fri, 26 Oct 2012
# Or specify a zone to use
> Date.today_in_zone('Sydney')
=> Sat, 27 Oct 2012
To use it, just throw this in a file like 'lib/date_extensions.rb' and require 'date_extensions'.
class Date
def self.today_in_zone(zone = ::Time.zone)
::Time.find_zone!(zone).today
end
end
I think the best way is to learn the current time through:
Time.current
This will automatically check to see if you have timezone set then it will call Time.zone.now, but if you've not it will call just Time.now.
Also, don't forget to set your timezone in application.rb
# system timezone
Time.now.to_date == Date.today
# application timezone
Time.zone.now.to_date == Time.current.to_date == Time.zone.today == Date.current
http://edgeapi.rubyonrails.org/classes/Time.html#method-c-current
http://edgeapi.rubyonrails.org/classes/Date.html#method-c-current

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