Question about working with dates

I have a list (in database) of weekday non-holiday dates that goes
from present back to 1990. From this list, I’d like to pull out dates
given different kinds of criteria and add them to an array. Examples
of criteria are:

  • first day of the month for the most recent 5 years. Perhaps obvious,
    but the first weekday non-holiday of the month isn’t necessarily day 1
    (i.e. 5/1).
  • first day of the month and one week after first day of the month for
    the most recent 5 years. If one week after first day of the month
    isn’t on the list, then I’d like the closest day thereafter.

Any thoughts on how best to do this? Code snippets would be greatly
appreciated.

seems like you could make an array of arrays out of your dates, with the
index being the number of the month, or a hash with the month’s name as
the key and an array of dates within the month as the value… that way
you could pull out the first index of each month and get the first
non-holiday weekday (not necessarily the 1st of the month, as you
mentioned,) and add 7 to get the next non-holiday weekday.

have you got some code you’re working with that you could post?

  • j

Also, it would be clearer to write something like this:

Saturday = 6
Sunday = 0
Weekend = [Saturday, Sunday]

while Weekend.include?(first_day_of_month.wday)
first_day_of_month += 1
end

eggman2001 wrote in post #995956:

I have a list (in database) of weekday non-holiday dates that goes
from present back to 1990. From this list, I’d like to pull out dates
given different kinds of criteria and add them to an array. Examples
of criteria are:

  • first day of the month for the most recent 5 years. Perhaps obvious,
    but the first weekday non-holiday of the month isn’t necessarily day 1
    (i.e. 5/1).

All it takes is a little math:

require ‘date’

#Create array of all weekday dates for last five years
#(probably faster than pulling them out of a database):

date_arr = []
previous_years = 5

1.upto(previous_years * 365) do |i|
new_date = today - i

next if [6,0].include?(new_date.wday)
date_arr << new_date
end

#Gather the first weekdays of each month:

results = []

date_arr.each do |date|
year = date.year
month = date.month
first_day_of_month = Date.new(year, month, 1)

while [6,0].include?(first_day_of_month.wday)
first_day_of_month += 1
end

if date == first_day_of_month
results << date
end
end

puts results

–output:–
2011-04-01
2011-03-01
2011-02-01
2011-01-03
2010-12-01
2010-11-01
2010-10-01
2010-09-01
2010-08-02
2010-07-01
2010-06-01
2010-05-03
2010-04-01
2010-03-01
2010-02-01
2010-01-01
2009-12-01
2009-11-02
2009-10-01
2009-09-01
2009-08-03
2009-07-01
2009-06-01
2009-05-01
2009-04-01
2009-03-02
2009-02-02
2009-01-01
2008-12-01
2008-11-03
2008-10-01
2008-09-01
2008-08-01
2008-07-01
2008-06-02
2008-05-01
2008-04-01
2008-03-03
2008-02-01
2008-01-01
2007-12-03
2007-11-01
2007-10-01
2007-09-03
2007-08-01
2007-07-02
2007-06-01
2007-05-01
2007-04-02
2007-03-01
2007-02-01
2007-01-01
2006-12-01
2006-11-01
2006-10-02
2006-09-01
2006-08-01
2006-07-03
2006-06-01
2006-05-01

You could benchmark whether adding the check below would be faster:

last_result = results[-1]

if last_result.is_a?(Date) and last_result.month == month
next
end

7stud – wrote in post #995994:

eggman2001 wrote in post #995956:

I have a list (in database) of weekday non-holiday dates that goes
from present back to 1990. From this list, I’d like to pull out dates
given different kinds of criteria and add them to an array. Examples
of criteria are:

  • first day of the month for the most recent 5 years. Perhaps obvious,
    but the first weekday non-holiday of the month isn’t necessarily day 1
    (i.e. 5/1).

All it takes is a little math:

require ‘date’

#Create array of all weekday dates for last five years
#(probably faster than pulling them out of a database):

date_arr = []
previous_years = 5

Hmmmm…looks like the following line got deleted somehow:

today = Date.today

1.upto(previous_years * 365) do |i|
new_date = today - i

next if [6,0].include?(new_date.wday)
date_arr << new_date
end

========

You could benchmark whether adding the check below would be faster:

last_result = results[-1]

if last_result.is_a?(Date) and last_result.month == month
next
end

This would be better:

last_result = results[-1]

begin
next if last_result.month == month
rescue NoMethodError
#do nothing
end

The rescue handles the initial case when the results array is empty,
so results[-1] returns nil. After the array has one element, then only
the single conditional will execute. That is more efficient than
creating a new Date object every time and doing a comparison.

Add year to Date object:
Multiply by 12 and add that many months (see below)

Subtract year from Date object:
Multiply by 12 and subtract that many months (see below)

Add month to Date object:
new_date = date >> 1

Subtract month from Date object:
new_date = date << 1 (or add a negative int)

Add day to Date object:
new_date = date + 1

Subtract day from Date object:
new_date = date - 1

eggman2001 wrote in post #995956:

  • first day of the month and one week after first day of the month for
    the most recent 5 years. If one week after first day of the month
    isn’t on the list, then I’d like the closest day thereafter.

Isn’t that just adding 7 days to each of the dates produced by your
first criteria?

require ‘date’

Saturday = 6
Sunday = 0
Weekend = [Saturday, Sunday]

results = []
today = Date.today

now = 0
years = -5
start_date = years * 12

start_date.upto(now) do |i|
date = today >> i
date = Date.new(date.year, date.month, 1)

while Weekend.include?(date.wday)
date += 1
end

results << date + 7
end

puts results

–output:–
2006-04-10
2006-05-08
2006-06-08
2006-07-10
2006-08-08
2006-09-08
2006-10-09
2006-11-08
2006-12-08
2007-01-08
2007-02-08
2007-03-08
2007-04-09
2007-05-08
2007-06-08
2007-07-09
2007-08-08
2007-09-10
2007-10-08
2007-11-08
2007-12-10
2008-01-08
2008-02-08
2008-03-10
2008-04-08
2008-05-08
2008-06-09
2008-07-08
2008-08-08
2008-09-08
2008-10-08
2008-11-10
2008-12-08
2009-01-08
2009-02-09
2009-03-09
2009-04-08
2009-05-08
2009-06-08
2009-07-08
2009-08-10
2009-09-08
2009-10-08
2009-11-09
2009-12-08
2010-01-08
2010-02-08
2010-03-08
2010-04-08
2010-05-10
2010-06-08
2010-07-08
2010-08-09
2010-09-08
2010-10-08
2010-11-08
2010-12-08
2011-01-10
2011-02-08
2011-03-08
2011-04-08

My list includes only weekday dates, so I’m not concerned about
weekend/weekday so long as I’m using this list. I’d like to pull out
the first day of each month from my list. Any chance you could give me
an idea of how to do this?

Yeah, look at the code I posted. It doesn’t matter whether you generate
the list with ruby code or get it from a database. Just substitute your
code that retrieves the dates from the database for my code that creates
the list of dates.

Note that my second example generates one date at a time and
then determines whether it is the first day of the month or not, which I
would think is much more efficient that querying a database for all
those dates, and then iterating over that list. In other words, your
database of dates is useless and is a waste of resources.

Or, are you asking, “I don’t know any ruby, and I want someone to write
the exact code I need?” If so, I’ll write the code for you for $200.
Let me know where to send my Paypal info.

Okay thank you for your help.

This is very helpful. The only thing is that I’d like to use my
existing list of dates (for certain reasons) as opposed to creating a
new list.

My list includes only weekday dates, so I’m not concerned about
weekend/weekday so long as I’m using this list. I’d like to pull out
the first day of each month from my list. Any chance you could give me
an idea of how to do this?

Thanks much.