How to convert date format in Ruby - ruby-on-rails

Here are some outputs:
Date.today => Mon, 25 Jun 2012
Date.today.to_formatted_s(:long_ordinal) => "June 25th, 2012"
Date.today.strftime('%A %d, %B') => "Monday 25, June"
Now I need output in the format ie:
Monday 25th, June or Thrusday, 1st, October
Problem is to_formatted_s and strftime apply only on date and both or them return string. How can I get the output in the way I need?

You can use Date::DATE_FORMATS to add a new customized format, and Integer.ordinalize to get the day ordinal:
Date::DATE_FORMATS[:month_ordinal] = lambda { |date|
date.strftime("%A #{date.day.ordinalize}, %B")
}
>> Date.today.to_formatted_s(:month_ordinal)
=> "Monday 25th, June"

Related

Formatting Date in Rails

How can I format this datetime attribute 2017-10-15 or how can I get the 15th of the current month?
#today = Time.now
#mid = time.strftime("%Y-%m-15")
into October 15, 2017? I tried using to_formatted_s(:long), but it gives an error of undefined method.
In Rails 4 or above
> Date.today.beginning_of_month + 14
#=> Sun, 15 Oct 2017
# formatted as per your requirement
> (Date.today.beginning_of_month + 14).strftime("%B %d, %Y")
#=> "October 15, 2017"
Date#beginning_of_month it will return you beginning date of month of specified date (which will be always 1st, add 14 days) so you will get 15th of that month
Mydate = "2017-10-15"
Mydate.to_date.strftime("%B %d, %Y")
=> "October 15, 2017"
Using #GaganGami solution, you can create a Date class method middle_of_current_month
class Date
def self.middle_of_current_month
(today.beginning_of_month + 14).strftime("%B %d, %Y")
end
end
Date.middle_of_current_month
#=> "October 15, 2017"

Date validation in Ruby

How to check if the date is valid date in ruby. Many of the methods are check only the range. But, I need to check the date with day of
week to check whether the date is valid or not. For Ex:
20 Jul 2016 Wed --> Valid
20 Jul 2016 Mon --> Not-Valid
How to do this in ruby ?
I'm not pretend on the best solution ever, but this should work.
def valid_date?(date)
Date.parse(date).strftime("%d %b %Y %a") == date
end
[55] pry(main)> valid_date?("20 Jul 2016 Wed")
=> true
[56] pry(main)> valid_date?("20 Jul 2016 Mon")
=> false
[57] pry(main)>
If you have many formats you may pass format as a second argument
def valid_date?(date, fmt)
Date.parse(date).strftime(fmt) == date
end
=> :valid_date?
[59] pry(main)> valid_date?("20 Jul 2016 Wed", "%d %b %Y %a")
=> true
Hope this will help.
UPDATE
As I mentioned in comment that method name overlaps with existing method valid_date?
So, you may just rename the custom method
def date_valid?(date, fmt)
Date.parse(date).strftime(fmt) == date
end
[2] pry(main)> date_valid?("20 Jul 2016 Wed", "%d %b %Y %a")
=> true
Just out of curiosity:
dates = ['20 Jul 2016 Wed', '20 Jul 2016 Mon']
dates.map do |date|
Date.parse(date).public_send(
Date.instance_methods.detect do |m|
m.to_s =~ /\A#{date[-3..-1].downcase}.*day\?\z/
end)
end
#⇒ [ true, false ]
require 'date'
dates = ['20 Jul 2016 Wed', '20 Jul 2016 Mon']
dates.select do |s|
d = Date.strptime(s[0,11], "%d %b %Y") rescue nil
d.nil? ? false : (Date::ABBR_DAYNAMES[d.wday] == s[-3,3])
end
#=> ["20 Jul 2016 Wed"]
This reads, "select strings 'dd mmm yyyy' that represent valid dates and whose day-of-week matches the day-of-week given by the last three characters of the string".

How do I push dates into an array by week?

I am writing this code that maps dates by day and pushes them into an array:
rtn_ary = []
(2.weeks.ago.to_date..Date.today).map do |date|
rtn_ary << {period: date}
end
How can I write the code if my expected result is based on weeks instead of days like this?
[[{:period=>Mon, 28 Sep 2015}, {:period=>Tue, 05 Oct 2015}, {:period=>Tue, 12 Oct 2015}]
A simple solution could be to iterate by 7 days instead of 1 day:
rtn_ary = (2.weeks.ago.to_date..Date.today).step(7).map do |date|
{period: date}
end
=> [{:period=>Mon, 28 Sep 2015}, {:period=>Mon, 05 Oct 2015}]
More info about step: http://ruby-doc.org/core-1.9.3/Range.html#method-i-step
To get what you want you'll need an additional step:
(2.weeks.ago.to_date..Date.today).map do |date|
rtn_ary << {period: date.to_formatted_s(:long)}
end
The to_formatted_s() method convert the date into a formatted string and takes a parameter which will define how the date will be formatted into a string.
date.to_formatted_s(:short) # => "10 Nov"
date.to_formatted_s(:number) # => "20071110"
date.to_formatted_s(:long) # => "November 10, 2007"
date.to_formatted_s(:long_ordinal) # => "November 10th, 2007"
date.to_formatted_s(:rfc822) # => "10 Nov 2007"
date.to_formatted_s(:iso8601) # => "2007-11-10"
Take a look at the rails Documentation

ROR + TodayDate in Different Format

If I have #today = Date.today.to_s, how do I convert #today into UTC (with the appropriate date only)? But the format should be like this : 2011-03-08 00:00:00
Acutally I am looking for Yesterday date also ??
This worked for me to get yesterday at time 00hr
Date.yesterday.to_time.utc.at_beginning_of_day
=> Sun Mar 06 00:00:00 UTC 2011
I don't know if its the correct way to do it but it works
ruby-1.9.2-p0 > Date.today.to_time.utc
=> 2011-03-07 18:15:00 UTC
and for yesterday, you can subtract a day form today
(Date.today-1.day).to_time.utc
=> 2011-03-06 18:15:00 UTC
For Yesterday Date.
#date = Date.yesterday
=> Mon, 07 Mar 2011
#date.to_time.utc.strftime("%Y-%m-%d %H:%M:%S")
=> "2011-03-06 18:30:00"
This will do(%F - %Y-%m-%d and %T - %H:%M:%S)
Date.today.strftime("%F %T")
Date.yesterday.strftime("%F %T")
If you are particular about UTC time, you should do like this
(Time.now.utc).to_date.strftime("%F %T")
(Time.now.utc - 1.day).to_date.strftime("%F %T")

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