Retrieve first and last day of the month with Ruby (DateTime) - ruby

How can i retrieve Retrieve first and last day of the month with Ruby (DateTime)?
I want to create invoices that start the first day and finishes the last day of the month.

Given a year and a month:
year = 2017
month = 5
You can pass these to Date.new along with a day value of 1 and -1 to get the first and last day respectively:
require 'date'
Date.new(year, month, 1) #=> #<Date: 2017-05-01 ...>
Date.new(year, month, -1) #=> #<Date: 2017-05-31 ...>

Use the beginning_of_month and end_of_month methods
irb(main):004:0> n = DateTime.now
=> Wed, 10 May 2017 14:48:01 +0300
irb(main):005:0> n.to_date.beginning_of_month
=> Mon, 01 May 2017
irb(main):006:0> n.to_date.end_of_month
=> Wed, 31 May 2017

Related

Use just Month and Year in date strings, to find which combination is older

I have a requirement to compare two date strings, and to find which is older month. there is no day parameter in both strings. Is there any pre build method available in Ruby or in any of its library?
Eg: 1) December, 2015
2) August, 2013
Find which date is older?
Sure, you can use the 'Date' library with the parse method like so:
require 'date'
=> true
date1 = Date.parse('December, 2015')
date2 = Date.parse('August, 2013')
date1 > date2
=> true
date2 > date1
=> false
Same as Anthony's answer, using time
require 'time'
a = "December, 2015"
b = "August, 2013"
t1 = Time.parse(a)
# => 2015-12-01 00:00:00 +0530
t2 = Time.parse(b)
# => 2013-08-01 00:00:00 +0530
t1 > t2
# => true

Use DateTime to print name of day from a date?

I am trying to use DateTime to go through a list of dates, and find the days of week (Monday, Tuesday, Wednesdat, &c.) that are most often associated with each date in the list.
I am trying this:
contents = CSV.open 'event_attendees.csv', headers: true, header_converters: :symbol
contents.each do |row|
times = contents.map { |row| row[:regdate] }
target_days = Hash[times.group_by { |t| DateTime.strptime(t, '%m/%d/%Y %H:%M').wday }.map{|k,v| [k, v.count]}.sort_by{ |k,v| v }.reverse]
puts target_days
I get:
{1=>6, 2=>5, 5=>4, 6=>2, 0=>1}
From what I understand wday will represent each day as 0(sunday), 1(monday), &c. I am stumped on how to convert this into the actual name of the day? Or how can this be converted to the abbreviated name (Sun, Mon, Tue, &c.)?
Also, I'm not positive the above is returning the correct days. Looking at my list, there are six dates for 11/12/2008. November 12, 2008 was a Wednesday — but it looks like it is showing that the most common day, with a count of 6, is Monday. So, I'm not sure that this is really counting the correct day of the week.
Can someone please explain why what I am doing doesn't seem to be counting the correct day of the week, also — how to convert this to the name of the day and abbreviated name?
Thank you!
You can convert the wday integers to full names using Date::DAYNAMES and abbreviated names using Date::ABBR_DAYNAMES:
Date::DAYNAMES[3]
#=> "Wednesday"
Date::ABBR_DAYNAMES[3]
#=> "Wed"
Update
As far as your algorithm goes, it looks right to me:
require "date"
times = [
"4/25/2014 00:00", # Friday
"4/21/2014 00:00", # Monday
"4/22/2014 00:00", # Tuesday
"4/20/2014 00:00", # Sunday
"4/22/2014 00:00", # Tuesday
"4/21/2014 00:00", # Monday
"4/21/2014 00:00", # Monday
"4/19/2014 00:00"] # Saturday
target_days = Hash[times.group_by do |time|
DateTime.strptime(time, "%m/%d/%Y %H:%M").wday
end.map do |key, value|
[Date::ABBR_DAYNAMES[key], value.count]
end.sort_by do |key, value|
value
end.reverse]
puts target_days
#=> {"Mon"=>3, "Tue"=>2, "Sat"=>1, "Sun"=>1, "Fri"=>1}
I would double check the contents of the file, and then step through the algorithm to see what's going wrong.
time = Time.new(2000)
# The full weekday name
puts time.strftime("%A")
# Saturday
# The abbreviated name
puts time.strftime("%a")
# Sat
See Time.strftime for more details. DateTime has the same implementation.

Ruby - Date ranges (from first of this month to first of next month)

I want to have something like this:
By example: If the first date is 2012-02-01 (YYYY-MM-DD), the next date has to be 2012-03-01. So increment the month.
However, if the date is 2012-12-01, the next date has to be 2013-01-01. I have managed to that doing nextMonth=((thisMonth) mod 12)+1 and setting nextYear to thisYear+1 if thisMonth = 12.
My question is: Can I do that easily using the Date library?
You can use Date#>>:
>> require 'date'
=> true
>> d = Date.new(2012,12,1)
=> #<Date: 2012-12-01 ((2456263j,0s,0n),+0s,2299161j)>
>> d >> 1
=> #<Date: 2013-01-01 ((2456294j,0s,0n),+0s,2299161j)>
>> (d..d>>1)
=> #<Date: 2012-12-01 ((2456263j,0s,0n),+0s,2299161j)>..#<Date: 2013-01-01 ((2456294j,0s,0n),+0s,2299161j)>
If the start date is not the first of the month but you still need the end date to be the first of the following month, you can do this:
>> d = Date.new(2012,12,12)
=> #<Date: 2012-12-12 ((2456274j,0s,0n),+0s,2299161j)>
>> (d>>1) - (d.mday - 1)
=> #<Date: 2013-01-01 ((2456294j,0s,0n),+0s,2299161j)>

How can I calculate the day of the week of a date in ruby?

How can I calculate the day of the week of a date in Ruby? For example, October 28 of 2010 is = Thursday
I have used this because I hated to go to the Date docs to look up the strftime syntax, not finding it there and having to remember it is in the Time docs.
require 'date'
class Date
def dayname
DAYNAMES[self.wday]
end
def abbr_dayname
ABBR_DAYNAMES[self.wday]
end
end
today = Date.today
puts today.dayname
puts today.abbr_dayname
Take a look at the Date class reference. Once you have a date object, you can simply do dateObj.strftime('%A') for the full day, or dateObj.strftime('%a') for the abbreviated day. You can also use dateObj.wday for the integer value of the day of the week, and use it as you see fit.
time = Time.at(time) # Convert number of seconds into Time object.
puts time.wday # => 0: Day of week: 0 is Sunday
Date.today.strftime("%A")
=> "Wednesday"
Date.today.strftime("%A").downcase
=> "wednesday"
Quick, dirty and localization-friendly:
days = {0 => "Sunday",
1 => "Monday",
2 => "Tuesday",
3 => "Wednesday",
4 => "Thursday",
5 => "Friday",
6 => "Saturday"}
puts "It's #{days[Time.now.wday]}"
Works out of the box with ruby without requiring:
Time.now.strftime("%A").downcase #=> "thursday"
As #mway said, you can use date.strftime("%A") on any Date object to get the day of the week.
If you're lucky Date.parse might get you from String to day of the week in one go:
def weekday(date_string)
Date.parse(date_string).strftime("%A")
end
This works for your test case:
weekday("October 28 of 2010") #=> "Thursday"
Say i have date = Time.now.to_date
then date.strftime("%A") will print name for the day of the week and to have just the number for the day of the week write date.wday.
In your time object, use the property .wday to get the number that corresponds with the day of the week, e.g. If .wday returns 0, then your date is Sunday, 1 Monday, etc.
basically the same answer as Andreas
days = ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday']
today_is = days[Time.now.wday]
if today_is == 'tuesday'
## ...
end

Is there an add_days in ruby datetime?

In C#, There is a method AddDays([number of days]) in DateTime class.
Is there any kind of method like this in ruby?
The Date class provides a + operator that does just that.
>> d = Date.today
=> #<Date: 4910149/2,0,2299161>
>> d.to_s
=> "2009-08-31"
>> (d+3).to_s
=> "2009-09-03"
>>
In Rails there are very useful methods of Fixnum class for this (here n is Fixnum. For example: 1,2,3.... ):
Date.today + n.seconds # you can use 1.second
Date.today + n.minutes # you can use 1.minute
Date.today + n.hours # you can use 1.hour
Date.today + n.days # you can use 1.day
Date.today + n.weeks # you can use 1.week
Date.today + n.months # you can use 1.month
Date.today + n.years # you can use 1.year
These are convenient for Time class too.
PS: require Active Support Core Extensions to use these in Ruby
require 'active_support/core_ext'
I think next_day is more readable than + version.
require 'date'
DateTime.new(2016,5,17)
# => #<DateTime: 2016-05-17T00:00:00+00:00 ((2457526j,0s,0n),+0s,2299161j)>
DateTime.new(2016,5,17).next_day(10)
# => #<DateTime: 2016-05-27T00:00:00+00:00 ((2457536j,0s,0n),+0s,2299161j)>
Date.new(2016,5,17)
# => #<Date: 2016-05-17 ((2457526j,0s,0n),+0s,2299161j)>
Date.new(2016,5,17).next_day(10)
# => #<Date: 2016-05-27 ((2457536j,0s,0n),+0s,2299161j)>
http://ruby-doc.org/stdlib-2.3.1/libdoc/date/rdoc/Date.html#method-i-next_day.
From the Date class:
+(n)
Return a new Date object that is n days later than the current one.
n may be a negative value, in which case the new Date is earlier than the current one; however, #-() might be more intuitive.
If n is not a Numeric, a TypeError will be thrown. In particular, two Dates cannot be added to each other.
Date.new(2001,9,01).next_day(30) # 30 - numbers of day
# => #<Date: 2001-10-01 ...
You can also use the advance (https://apidock.com/rails/DateTime/advance) method. I think it's more legible.
date = Date.today
# => Fri, 25 Oct 2019
date.advance(days: 10)
# => Mon, 04 Nov 2019
time = DateTime.now
# => Fri, 25 Oct 2019 14:32:53 +0200
time.advance(months:1, weeks: 2, days: 2, hours: 6, minutes: 6, seconds: 34)
# => Wed, 11 Dec 2019 20:39:27 +0200

Resources