Ruby Year-Month-Date of last Sunday - ruby-on-rails

I need to calculate in the format of 2014-01-20 the last two Sundays.
So, last_sunday = 2014-01-20 and most_recent_sunday = 2014-01-26.
I am using Rails 4.0 and Ruby 2.0. How can I get these dates?

In rails 4:
most_recent_sunday = Time.now.sunday.to_s
last_sunday = Time.now.last_week.sunday.to_s
To get it to the format you are after:
DateTime.parse(most_recent_sunday).strftime("%Y-%m-%d")
http://apidock.com/rails/v4.0.2/DateAndTime/Calculations/sunday
http://apidock.com/rails/v4.0.2/DateAndTime/Calculations/last_week

I suggest you take a look at the chronic gem
require 'chronic'
Chronic.parse("last sunday")
=> 2014-01-26 12:00:00 +0200
You can also use rail's active_support to subtract 7.days from the date computed above =)

[11] pry(main)> last_sunday = Time.now - (Time.now.wday + 7) * 86400
=> 2014-01-19 17:17:19 -0600
[12] pry(main)> most_recent_sunday = Time.now - (Time.now.wday) * 86400
=> 2014-01-26 17:18:03 -0600

A pure Ruby solution:
require 'date'
last_two_weeks = (Date.today-13)..Date.today
last_two_sundays = last_two_weeks.select &:sunday?
puts last_two_sundays #=> 2014-01-19, 2014-01-26

Related

beginning_of_day doesn't calculate time correctly

I got two models Shift and ShiftDetail. I have a Shift model methods that adds ShiftDetails automatically:
def add_shift_details
(0..6).each do |i|
shift_detail = ShiftDetail.new
t1 = Time.now
shift_detail.weekday = i
shift_detail.start_time = t1.beginning_of_day
shift_detail.end_time = t1.end_of_day
self.shift_details << shift_detail
end
end
But when i save the instance the database is populated with
["start_time", "2016-03-02 23:00:00.000000"]
["end_time", "2016-03-03 22:59:59.999999"]
I am using Rails 4.2.5.1 and ruby 2.3.0p0
What am I doing wrong?
UPDATE:
When I test it in 'rails c', it works as expected:
2.3.0 :001 > Time.now.beginning_of_day
=> 2016-03-03 00:00:00 +0100
2.3.0 :002 > Time.now.end_of_day
=> 2016-03-03 23:59:59 +0100
Your database stores DateTime in the UTC timezone while Rails works with the Berlin timezone. Berlin's midnight (GMT+1) is not equal with UTC's (GMT) midnight :)
You have two options:
Have your algorithm work with an UTC timezone
You can use Time.now.utc or DateTime.now.new_offset(0)
Have your database store dates in your specific timezone (Berlin's in this case). I highly advise not to do this.
Check out this post for more information:
https://stackoverflow.com/a/32229086/4304188

Calculate total time in minutes between two timings in two diff. time zones (UTC and IST) - Rails 3.2.13

I have two datetimes formats to calculate the difference.
2013-08-29 22:48:00 UTC
2013-08-30 00:18:40 +0530
How can I get the first subtracted from the second one? What is actually the difference between them other than in time?
Below are the things I run in my console:
Loading development environment (Rails 3.2.13)
2.0.0-p247 :001 > #a = Time.parse('2013-08-29 22:48:00 UTC')
=> 2013-08-29 22:48:00 UTC
2.0.0-p247 :002 > #b = Time.parse('2013-08-29 22:48:00 +0530')
=> 2013-08-29 22:48:00 +0530
2.0.0-p247 :003 > #a > #b
=> true
2.0.0-p247 :004 > #a == #b
=> false
2.0.0-p247 :005 > #a < #b
=> false
2.0.0-p247 :006 >
Both are not the same, so the answer from cmwright is found to be incorrect. Please have a look and it would be great if you could tell me how can we convert UTC format to +5.30 format in Rails 3.2?
seconds_difference = Time.parse('2013-08-29 22:48:00 UTC') - Time.parse('2013-08-30 00:18:40 +0530')
Will give you the seconds difference, then you can get you need from there by doing
seconds_difference / 1.day or seconds_difference / 1.hour
What is actually the difference between them other than in time?
Well, one date is at UTC (+00:00) and the other is at UTC+05:30.
2013-08-29 22:48:00 UTC => 2013-08-30 04:18:00 +0530
- 2013-08-29 18:48:40 UTC <= - 2013-08-30 00:18:40 +0530
------------------------- ---------------------------
3:59:20 3:59:20
Whichever direction you convert, they are 3 hours, 59 minutes, and 20 seconds apart.
CMWright's answer shows how you can subtract them in code. The integers you get from the Time.parse function are both based on UTC.

Ruby Time.now and Other dates

I need to get three dates in variables
Today Since Midnight which I have as
t = Time.now.strftime("%Y-%m-%d 00:00:01") # 2012-11-19 00:00:01
Yesterday Since Midnight (i.e. 00:00:00 to 23:59:59)
y1 = 2012-11-18 00:00:01
y2 = 2012-11-19 23:59:59
it is specifically the y1 & y2 variables I need to create as strings for use in a gem. being new to ruby I am a little confused as Time.yesterday doesn't seem to do what I need
EDIT
For this be sure to include
require 'active_support/all'
and ensure the gem is bundled for your application.
Used:
#current = (Time.now).beginning_of_day.utc.strftime("%Y-%m-%d")
#yesterday = (Time.now - 1.day).beginning_of_day.utc.strftime("%Y-%m-%d")
#everything = (Time.now - 2.day).end_of_day.utc.strftime("%Y-%m-%d")
You can do,
t=Time.now
y1=t-1.day
y2=t+1.day
t = Time.now
t - 1.day # => yesterday
t + 1.day # => tomorrow
convert t to date first,
t = t.to_date
t - 1.day # => yesterday
t + 1.day # => tomorrow
Since you are running Rails there's help to get from ActiveSupport
1.day.ago.midnight
Time.new.beginning_of_day
You should also consider not using 2012-11-19 00:00:01 or 2012-11-19 23:59:59.
Instead you could use 00:00:00 and compare with >= or < depending on what you want to achieve. If you always round to seconds then 2012-11-19 00:00:00 to 2012-11-19 23:59:59 would work.

How to add minutes to a Time object

In Ruby, how do I do Time.now + 10.hours?
Is there an equivalent for secs and mins? For example:
Time.now + 15.mins
Ruby (the programming language) doesn't have 10.hours, that's ActiveSupport as part of Ruby on Rails (the web framework). And yes, it does have both minutes and seconds methods.
However, Time#+ (the + method on Time instances) returns a new Time instance that is that many seconds in the future. So without any Ruby on Rails sugar, you can simply do:
irb> t = Time.now
#=> 2011-08-03 22:35:01 -0600
irb> t2 = t + 10 # 10 Seconds
#=> 2011-08-03 22:35:11 -0600
irb> t3 = t + 10*60 # 10 minutes
#=> 2011-08-03 22:45:01 -0600
irb> t4 = t + 10*60*60 # 10 hours
#=> 2011-08-04 08:35:01 -0600
If you are using ActiveSupport, what you are looking for is the full .minutes and .seconds.
Time.now + 10.minutes
Time.now + 10.seconds
Also in ActiveSupport you can do:
10.minutes.from_now
10.minutes.ago
I think you're talking about extensions added by Rails. I think you need 15.minutes.
See the Active Support Core Extensions for Date, DateTime and Time for more information.
Time Object
time = Time.now
Adding minutes to a time object:
time + 5.minutes
There is an advance function in Active Support refer.
You can do the following using advance:
d = DateTime.new(2010, 2, 28, 23, 59, 59)
=> Sun, 28 Feb 2010 23:59:59 +0000
d.advance(hours: 1)
=> Mon, 01 Mar 2010 00:59:59 +0000

Ruby on Rails 3 Time - Parse Milliseconds

I'm trying to parse a date like: 2011-05-21 04:20:46.011 into a Time object in Rails. So far I have the following:
Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
But it doesn't seem to like the "%3N" at the end. How do I parse this date?
Use parse:
x = Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
# => 2011-05-21 04:20:46 -0700
x.usec
# => 11000
In many case you don't need to pass in the format either:
x = Time.parse("2011-05-21 04:20:46.011")
# => 2011-05-21 04:20:46 -0700
x.usec
# => 11000
Try Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
With Ruby v 2.3.2 and Rails v 5.0.0.1 in rails console
2.3.2 :035 > Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%3N")
NoMethodError: undefined method `getlocal' for "%Y-%m-%d %H:%M:%S.%3N":String
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:264:in `make_time'
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:366:in `parse'
from (irb):35
Note: In code below in the parse format, NOT prefixed %N with the number of fractional digits like %3N and instead simply specified %N and it works
2.3.2 :037 > Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
=> 2011-05-21 04:20:46 +0530
2.3.2 :038 > tt = Time.strptime("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
=> 2011-05-21 04:20:46 +0530
2.3.2 :039 > tt.usec
=> 11000
The above code didn't worked when using parse
2.3.2 :040 > tt = Time.parse("2011-05-21 04:20:46.011", "%Y-%m-%d %H:%M:%S.%N")
NoMethodError: undefined method `getlocal' for "%Y-%m-%d %H:%M:%S.%N":String
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:264:in `make_time'
from /home/jignesh/.rvm/rubies/ruby-2.3.2/lib/ruby/2.3.0/time.rb:366:in `parse'
from (irb):40
It looks strange because Time.strptime(date, format, now=self.now) official documentation does mention about %3N, %6N and %9N explicitly and using them in the parse format doesn't work!
Rails does provide a counterpart strptime(str, format, now=now()) as part of ActiveSupport::TimeZone API and it internally does the parsing using Ruby's standard DateTime._strptime as shown in its source-code:
# File activesupport/lib/active_support/values/time_zone.rb, line 382
def strptime(str, format, now=now())
parts_to_time(DateTime._strptime(str, format), now)
end
And I guess DateTime._strptime internally delegates to Ruby's standard Time.strptime
For those who are looking for leveraging Rails's Time.zone.parse counterpart for parsing in a specific format they can use below code:
tt = Time.zone.strptime('1999-12-31 14:00:00.011111', '%Y-%m-%d %H:%M:%S.%N')
=> Fri, 31 Dec 1999 14:00:00 UTC +00:00
2.3.2 :031 > tt.usec
=> 11111
Hope someone from the core-team can clarify about this behaviour observed and if the behaviour is normal then at-least a note should be made about in the documentation.

Resources