Formatting Date in Rails - ruby-on-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"

Related

Efficient way to get closest pay day to a given date

I'm trying to figure out the most efficient way to find the closest payday from a given date.
Let's say we know payday are every 14 days and that January 6, 2022 was one of them. What is the most efficient way to find the next payday for a given date (the date is the beginning of a week actually) from a known payday?
Here is a current working ugly implementation
def payday_first_date
# TODO: Very reliable, but very inefficient
#payday_first_date ||= begin
date = known_pay_day
date -= 14.days until date < given_date
date += 14.days until date > given_date
date
end
end
def known_pay_day
# Thursday January 6, 2022 was a payday
#known_pay_day ||= Date.new(2022, 2, 17)
end
The given_date could be in the future and also in the past. It can be a date from another year aswell.
Thanks in advance!
First define the known pay date and two helper methods.
require 'date'
def date_str_to_date_obj(date_str)
DateTime.strptime(date_str, "%B %d, %Y").to_date
end
known_date = date_str_to_date_obj("January 6, 2022")
#=> #<Date: 2022-01-06 ((2459586j,0s,0n),+0s,2299161j)>
For presentation only:
def date_obj_to_date_str(date_obj)
date_obj.strftime("%B %d, %Y, %A")
end
date_obj_to_date_str(known_date)
#=> "January 06, 2022, Thursday"
The main method follows.
def closest_pay_day(known_date, target_date)
nbr_pay_dates = (target_date - known_date)/14.0
last_pay_date = known_date + nbr_pay_dates.floor * 14
next_pay_date = last_pay_date + 14
(next_pay_date - target_date < target_date - last_pay_date) ?
next_pay_date : last_pay_date
end
Suppose the target date is after the known pay date.
target_date_str = "March 26, 2022"
Then
target_date = date_str_to_date_obj(target_date_str)
#=> #<Date: 2022-03-26 ((2459665j,0s,0n),+0s,2299161j)>
date_obj_to_date_str(target_date)
#=> "March 26, 2022, Saturday"
The closest pay period to the target date is therefore
closest = closest_pay_day(known_date, target_date)
#=> #<Date: 2022-03-31 ((2459670j,0s,0n),+0s,2299161j)>
date_obj_to_date_str(closest)
#=> "March 31, 2022, Thursday"
which is
(target_date- closest).to_i
#=> -5
days before the target date, meaning 5 days after the target date.
Now suppose the target date is before the known pay date.
target_date_str = "October 19, 2021"
Then
target_date = date_str_to_date_obj(target_date_str)
#=> #<Date: 2021-10-19 ((2459507j,0s,0n),+0s,2299161j)>
date_obj_to_date_str(target_date)
#=> "October 19, 2021, Tuesday"
date_obj_to_date_str(closest_pay_day(known_date, target_date))
#=> "October 14, 2021, Thursday"

Convert Time.zone.now to number OLE

I need convert the DateTime to OLE, Actually I have this code
def self.convert_time(t=42941.6102054745)
Time.at((t - 25569) * 86400).utc
end
but this converts to DateTime now I want this solution :
def self.date_time_ole(dt= Time.zone.now)
# her convert to number ole from datetime
end
could you please help me ?
Ruby's Date class subtraction returns number of days between 2 dates, so you just need to subtract your "custom epoch" (December 30, 1899 at midnight) from the other date:
ole_epoch = DateTime.new(1899, 12, 30, 0, 0, 0)
now = DateTime.now # => 2017-08-18 21:03:28 UTC
(now - ole_epoch).to_f # => 42965.87741847492
and that should be OLE and you can also just add it to go the other way:
ole_epoch + 42965.87741847492 # => Fri, 18 Aug 2017 21:03:28 +0000

How to convert date format in Ruby

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"

How do I calculate the next annual occurrence of a date?

Given a Ruby date, does a one liner exist for calculating the next anniversary of that date?
For example, if the date is May 01, 2011 the next anniversary would be May 01, 2012, however if it is December 01, 2011, the next anniversary is December 01, 2011 (as that date hasn't yet arrived).
If you date variable is an instance of Date then you can use >>:
Return a new Date object that is n months later than the current one.
So you could do this:
one_year_later = date >> 12
The same approach applies to DateTime. If all you have is a string, then you can use the parse method:
next_year = Date.parse('May 01, 2011') >> 12
next_year_string = (Date.parse('May 01, 2011') >> 12).to_s
IMHO you're better off using the date libraries (Date and DateTime) as much as possible but you can use the Rails extensions (such as 1.year) if you know that Rails will always be around or you don't mind manually pulling in active_support as needed.
An excellent gem exists for doing this called recurrence. You can checkout the source code or some samples:
https://github.com/fnando/recurrence
http://blog.plataformatec.com.br/tag/recurrence/
For example, if you have a date set you could try:
date = ...
recurrence = Recurrence.new(every: :year, on: [date.month, date.day])
puts recurrence.next
You can do it using Ruby's Date class:
the_date = Date.parse('jan 1, 2011')
(the_date < Date.today) ? the_date + 365 : the_date # => Sun, 01 Jan 2012
the_date = Date.parse('dec 31, 2011')
(the_date < Date.today) ? the_date.next_year : the_date # => Sat, 31 Dec 2011
Or, for convenience use ActiveSupport's Date class extensions:
require 'active_support/core_ext/date/calculations'
the_date = Date.parse('jan 1, 2011')
(the_date < Date.today) ? the_date.next_year : the_date # => Sun, 01 Jan 2012
the_date = Date.parse('dec 31, 2011')
(the_date < Date.today) ? the_date.next_year : the_date # => Sat, 31 Dec 2011
Try this:
def next_anniversary(d)
Date.today > d ? 1.year.from_now(d) : d
end
Pulling in a gem just to do this is overkill.
your_date > Date.today ? your_date : your_date >> 12

Transforming Datetime into month, day and year?

I can't seem to find this and I feel like it should be easy. In Ruby on Rails, how do I take:
2010-06-14 19:01:00 UTC
and turn it into
June 14th, 2010
Can I not just use a helper in the view?
I don't know for
June 14th, 2010
But if you want
June 14, 2010
Ref how do i get name of the month in ruby on Rails? or this
Just do
#date = Time.now
#date.strftime("%B %d, %Y")
And for suffix use following
#date.strftime("%B #{#date.day.ordinalize}, %Y") # >>> Gives `June 18th, 2010`
Time and date formats in rails:
Date
====
db:‘%Y-%m-%d’ 2008-08-20
long_ordinal:‘&proc’ August 20th, 2008
long:‘%B %e, %Y’ August 20, 2008
rfc822:‘%e %b %Y’ 20 Aug 2008
number:‘%Y%m%d’ 20080820
short:‘%e %b’ 20 Aug
DateTime
====
db:‘%Y-%m-%d’ 2008-08-20 16:56:21
long_ordinal:‘&proc’ August 20th, 2008 16:56
long:‘%B %e, %Y’ August 20, 2008 16:56
rfc822:‘%e %b %Y’ Wed, 20 Aug 2008 16:56:21 -0600
number:‘%Y%m%d’ 20080820165621
short:‘%e %b’ 20 Aug 16:56
Time
====
db:‘%Y-%m-%d %H:%M:%S’ 2008-08-20 16:56:21
long_ordinal:‘&proc’ August 20th, 2008 16:56
long:‘%B %d, %Y %H:%M’ August 20, 2008 16:56
rfc822:‘%a, %d %b %Y %H:%M:%S %z’ Wed, 20 Aug 2008 16:56:21 -0600
short:‘%d %b %H:%M’ 20 Aug 16:56
number:‘%Y%m%d%H%M%S’ 20080820165621
time:‘%H:%M’ 16:56
for example:
<%= news.created_at.strftime("%B %d, %Y %H:%M") %>
Thanks http://onrails.org/2008/08/20/what-are-all-the-rails-date-formats.html
For future reference: Rails date time formats
You don't need to save it in a variable.
Time.now.strftime("%Y-%m-%d") # 2013-01-08
Needs the Time module for Time.parse and ActiveSupport for Integer#ordinalize:
require 'time'
require 'active_support'
input = '2010-06-14 19:01:00 UTC'
t = Time.parse(input)
date = "%s %s, %d" % [t.strftime("%B"), t.day.ordinalize, t.year]
# => "June 14th, 2010"
Just the other day there was a similar question. In my answer how do I get name of the month in ruby on Rails? I showed how you can add a custom to_s definition in your config/environment.rb file.
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.merge!(
:my_own_long_date_format => "%B %d, %Y")
Now you can call Time.now.to_s(:my_own_long_date_format) from any view to get:
June 15, 2010
Update that is working in Rails 5 :
<%= l #user.created_at, format: :short %>
Internationalize :
<%= I18n.l( #user.created_at, format: :short) %>
You can use :long instead of :short

Resources