Given a Ruby DateTime how can I determine if it represents a day in the current work week? - ruby

I have a Ruby DateTime instance and I would like to know it is within the current week (Monday-Sunday). I'm not using Rails.
My guess is that I'd need to get the dates of Monday and Sunday for the current week and test whether my date lies between them.

Date.parse("Monday") # get the Monday date of current week
=> #<Date: 2015-10-26 ((2457322j,0s,0n),+0s,2299161j)>
Date.today.between?(Date.parse("Monday"), Date.parse("Monday") + 7)
=> true
DateTime.now.between?(Date.parse("Monday"),Date.parse("Monday") + 7)
=> true

Related

How do you set a default format for dates in a hash? [duplicate]

I am trying to return a date with this format
2015-10-07T00:32:50.877+0000
I have tested that
Time.now.iso8601
=> "2015-10-21T09:47:50-04:00"
but i didn't have same format
tks
You can use strftime yourself and create the format you want as described here
The format you specified should be %Y-%m-%dT%H:%M:%S.%L%z
And so the complete Ruby statement would be Time.now.strftime('%Y-%m-%dT%H:%M:%S.%L%z')
Various ISO 8601 formats:
%Y%m%d => 20071119 Calendar date (basic)
%F => 2007-11-19 Calendar date (extended)
%Y-%m => 2007-11 Calendar date, reduced accuracy, specific month
%Y => 2007 Calendar date, reduced accuracy, specific year
%C => 20 Calendar date, reduced accuracy, specific century
%Y%j => 2007323 Ordinal date (basic)
%Y-%j => 2007-323 Ordinal date (extended)
%GW%V%u => 2007W471 Week date (basic)
%G-W%V-%u => 2007-W47-1 Week date (extended)
%GW%V => 2007W47 Week date, reduced accuracy, specific week (basic)
%G-W%V => 2007-W47 Week date, reduced accuracy, specific week (extended)
%H%M%S => 083748 Local time (basic)
%T => 08:37:48 Local time (extended)
%H%M => 0837 Local time, reduced accuracy, specific minute (basic)
%H:%M => 08:37 Local time, reduced accuracy, specific minute (extended)
%H => 08 Local time, reduced accuracy, specific hour
%H%M%S,%L => 083748,000 Local time with decimal fraction, comma as decimal sign (basic)
%T,%L => 08:37:48,000 Local time with decimal fraction, comma as decimal sign (extended)
%H%M%S.%L => 083748.000 Local time with decimal fraction, full stop as decimal sign (basic)
%T.%L => 08:37:48.000 Local time with decimal fraction, full stop as decimal sign (extended)
%H%M%S%z => 083748-0600 Local time and the difference from UTC (basic)
%T%:z => 08:37:48-06:00 Local time and the difference from UTC (extended)
%Y%m%dT%H%M%S%z => 20071119T083748-0600 Date and time of day for calendar date (basic)
%FT%T%:z => 2007-11-19T08:37:48-06:00 Date and time of day for calendar date (extended)
%Y%jT%H%M%S%z => 2007323T083748-0600 Date and time of day for ordinal date (basic)
%Y-%jT%T%:z => 2007-323T08:37:48-06:00 Date and time of day for ordinal date (extended)
%GW%V%uT%H%M%S%z => 2007W471T083748-0600 Date and time of day for week date (basic)
%G-W%V-%uT%T%:z => 2007-W47-1T08:37:48-06:00 Date and time of day for week date (extended)
%Y%m%dT%H%M => 20071119T0837 Calendar date and local time (basic)
%FT%R => 2007-11-19T08:37 Calendar date and local time (extended)
%Y%jT%H%MZ => 2007323T0837Z Ordinal date and UTC of day (basic)
%Y-%jT%RZ => 2007-323T08:37Z Ordinal date and UTC of day (extended)
%GW%V%uT%H%M%z => 2007W471T0837-0600 Week date and local time and difference from UTC (basic)
%G-W%V-%uT%R%:z => 2007-W47-1T08:37-06:00 Week date and local time and difference from UTC (extended)
If you just want to include the fractional number of seconds, you can use DateTime#iso8601([n=0]) → string:
pry(main)> require 'date'
pry(main)> DateTime.now.iso8601(3)
=> "2017-01-17T12:31:26.695+11:00"
Or in Rails:
pry(main)> Time.now.iso8601(3)
=> "2017-01-17T12:31:26.695+11:00"
It seems like the main issue is that you want the output to be UTC encoded ISO 8601 timestamp, while Ruby by default uses the timezone of the Time value - which is most likely, especially if you create the value using Time.now, your local time zone.
The solution would be to convert the Time value to a UTC timezone using #utc method:
now = Time.now
# convert to UTC and format
puts now.utc.iso8601
This would output 2020-04-20T20:46:31Z - the Z there is equivalent to +00:00 and means UTC (or "Zulu time" in US military jargon). Any ISO-8601 compliant implementation should accept Z being identical to +00:00.
Note:
The iso8601 method on the Time instance is an extension. It is part of the standard library, but you have to load it explicitly using require 'time'. This also loads other useful extensions for the Time class.
Did you try with Date?
Date.new(2018,5,25).iso8601 # returns "2018-05-25"
For today, it would be:
Date.today.iso8601
For a UTC time in ISO 8601:
require 'date'
DateTime.now.new_offset(0).iso8601
# => "2022-04-15T16:33:17+00:00"
(This works even outside of Rails.)

Get the last day of the month given the month

How would I get the last day of a current month given the month number.
For example if the month is 8 (August 2014), how would I get the last day of the month? (The last day of August is the 31th). The function(8) would return 31.
Thank you for the help.
Using Date::civil:
require 'date'
Date.civil(2014, 8, -1).day
# => 31
According to the documentation:
The month and
the day of month should be a negative or a positive number (as a
relative month/day from the end of year/month when negative).
They should not be zero.
require 'date'
def function(month)
raise "invalid month" unless month.is_a?(Integer) and month.between?(1, 12)
month == 12 ? 31 : Date.new(Date.today.year,month+1,1).prev_day.day
end
function(8)
# => 31
source: http://www.ruby-doc.org/stdlib-1.9.3/libdoc/date/rdoc/Date.html#method-i-prev_day

Determine the amount of clicks required to reach a specific date using a JQuery calendar?

I have a jquery calendar for the start date of a project.
Using Watir (automated browser driver, a gem for ruby), I have a set date that I would like to enter in.
The calendar start date is always today's date, whatever that may be for the day it is used. I was wondering if there was a way that ruby can process what today's date is, and use the specified date provided by the user, to calculate the difference of months between them.
Here is an example of the Calendar plugin: http://jqueryui.com/datepicker/
example:
today's date is 30/10/2012, if there was a project that were to start on the 20/12/2012, that would be 2 months from now, so 2 clicks on the next month button.
Is there a way I could do this?
Here is how I approached a similar situation with JSdatepicker:
$today = Time.now.strftime("%e").gsub(" ", "") #one digit day of month without leading space
#browser.text_field(:id => /dateAvailable/).click
Watir::Wait.until(60) {#browser.div(:id => /dateAvailable_popup_cal/).td(:text => $today).exists?}
#browser.div(:id => /dateAvailable_popup_cal/).td(:text => $today).click
Set or grab the date.
Click the text_field that fires the JSDatePicker object
Wait until the calendar actually pops up
The current month is shown, so choose today's date number.
In your case, you also need to set the month. Whether prompting the user for this, or choosing "today", the theory is the same:
$month = Date::MONTHNAMES[Date.today.month] #etc
Pseudo-code making lots of assumptions (only future dates, month name shown on calendar as text, etc):
while !#jquerytablewindow.text.include?($month)
next_month_button.click
end
I don't see a specific advantage to my method versus counting each month, unless of course we add a month to the calendar one day and you still want your code to work!
You could do:
#End date converted to date object
specified_date = '20/12/2012'
end_date = Date.parse(specified_date)
#Start date (today - 30/10/2012)
today = Date.today
#Determine difference in months
number_of_months_up_to_today = (today.month + today.year * 12)
number_of_months_up_to_end = (end_date.month + end_date.year * 12)
clicks_required = number_of_months_up_to_end - number_of_months_up_to_today
#=> 2
Basically it is counting the number of months since the year 0 and then finding the difference.

Return date if within date range

I have an object which contains a list of due dates, I am trying to build a system which returns the due date when a specified date is 1 month or less before the due date. It should return the due date in this format "1st Feb 2009". Let me clarify, using my current code
#Build array of estate objects
estate.due_dates = "1st Feb, 3rd May, 1st Aug, 5th Nov"
estate2.due_dates = "28th Feb, 31st May, 31st Aug, 30th Nov"
estates = [estate,estate2]
set_due_date_on_estates("1st Jan 2009",estates) #Run function - should return "1st Feb 2009,28th Feb 2009"
def set_due_date_on_estates(date,estates)
estates.each{|estate|
estate.due_dates.split(",").each{|due_date|
((date)..(date >> 1)).each{|current_date|
estate.set_reminder(due_date + current_date.strftime("%Y")) if current_date.strftime('%d %m') ==
Date.parse(due_date).strftime('%d %m')
}
}
end
}
The issue I am having, is that my list of due dates doesnt have a Year, so I am looping through my range and checking if the dates are equal using the format "%d %m". If so I am setting the reminder in the estate object by using the current "due date" in the loop concatenated with the Year of the "current date" in the loop.
Am not too happy with the code, in particular the nested loops and wondered if there was a better way I could deal with checking that the due_dates where in the date range, even though the due_dates dont have a year. Thanks
You could use date parsers: Kronos, chronic
Example for kronos:
def parse_date(date)
Kronos.parse(date.sub(/\d{4}$/, ''))
end
This function gives you a Kronos object without year which is more easily to compare, build range and so on.
Yes you can use Chronic and also you can write a worker which will keep checking if the specified date is 1 month or less before the due date at regular interval. And ask that worker to do something if result is true (say send you an email or anything if date is within due date) you can find more information about worker by googling Resque and Redis. Another option would be to convert both dates on some base reference and then do the calculations.

How can I create DateTime object based on the day?

I want to create an Datetime object based on the number of day in the year.
This number is from the 365 days of the year (for example it can be: 123 or 23 or 344...)
How can I do that?
Thanks
Use the DateTime.ordinal method. Here's an example to get the 100th day of year 2011.
require 'date'
year, day = 2011, 100
DateTime.ordinal(year, day)
# #<DateTime: 2011-04-10T00:00:00+00:00 (4911323/2,0,2299161)>
If you want it as the number of days from now you should do the following:
time = Time.new + (60*60*24)*(numberOfDaysFromNow)
If you want it as the number of days from the start of the year you should do the following
time = Time.new(Time.now.year) + (60*60*24)*(dayOfTheYear-1)

Resources