alexggordon
alexggordon

Reputation: 622

Getting range of dates from a date object in ruby

So I have a method that I pass in two date objects (project_start_date and project_end_date). My goal is to get the range between these objects so as I can add all those dates to an array and then if they check a box like repeat weekly, then I can add a new Milestone for every week until the project_end_date.

Now, as testing, this worked fine as a Ruby script, but does not appear to work now as a method in rails (disclaimer, I didn't write the original script). Specifically, the function is crashing on the range portion ((project_start_date..project_end_date).each) of the function. I don't think it's an issue with the actual date object, although I do think it is weird how rails stores the date in sub-elements.

If it would help, the way I pass in the date object to the method is I store the end_date and then call the method with the stored variable.

Call to method.

p_start_date = params[:new_basecamp_project][:start_date]
p_start_date.to_s
p_end_date = params[:new_basecamp_project][:end_date]
p_end_date.to_s

Function in it's entirety.

    date_array = []
(project_start_date..project_end_date).each do |date| 

    if (date.strftime("%A") != "Sunday") && (date.strftime("%A") != "Saturday")
        date_array << date
    end

end

weeks = {}
week_num = 1    
single_week_array = []
date_array.each do |date|

    if date.strftime("%A") != "Friday" && (date.to_s) != (date_array.last).to_s
        single_week_array << date
    elsif date.strftime("%A") == "Friday" || (date.to_s) == (date_array.last).to_s
        single_week_array << date
        weeks.merge!(week_num => single_week_array)
        week_num += 1
        single_week_array = []
    end

end
milestones.each do |milestone|

    if milestone.has_key?("duration")
        week_number = milestone["week_number"]
        day_number = milestone["day_number"]
        duration = milestone["duration"]
        start_date = weeks[week_number][(day_number - 1)]
        end_date = date_array[date_array.index(start_date) + (duration - 1)]

        if start_date == nil
            puts "Week or Day number out of range project dates! Milestone start date set to project end date"
            start_date = end_date
        end

        if end_date == nil
            puts "Duration out of range of project dates! Milestone end date set to project end date"
            end_date = project_end_date
        end
        Basecamp::CalendarEntry.new(:project_id => project_hash.id, "title" => milestone["description"], "start-at" => start_date, :deadline => end_date, :type => "CalendarEntry").save                
    else
        (project_start_date..project_end_date).each do |date|

            if date.strftime("%A") == milestone["repeat_weekly"]
                Basecamp::CalendarEntry.new(:project_id => project_hash.id, "title" => milestone["description"], "start-at" => date, :deadline => date, :type => "CalendarEntry").save
            end
        end
    end
end

Upvotes: 0

Views: 1178

Answers (2)

Douglas G. Allen
Douglas G. Allen

Reputation: 2261

Here is a simple example.

@year         = Time.now.utc.year
@start        = Date.parse("#{@year}-1-1")
@finish       = Date.parse("#{@year}-12-31")
@span         = 0..(@finish - @start).to_i
@span.each do |i|
  p i
end

This only does the day numbers but it could be easily adopted to your needs.

Upvotes: 1

Beartech
Beartech

Reputation: 6411

You are doing this:

p_end_date = params[:new_basecamp_project][:end_date]
p_end_date.to_s

This does not convert p_end_date to a string object. If you reassigned it, it would.

p_end_date = p_end_date.to_s

Also p_end_date = params[:new_basecamp_project][:end_date] does not create a DateTime object, when you do a save to the database it will create those DateTime object on save. You will have to do that manually if you want to manipulate them in this way before the save. Depending on how you are getting the Date in your form (date picker, date hash, etc) you will need to create the DateTime object. You can see some examples here: Where is the Rails method that converts data from `datetime_select` into a DateTime object?

So the easiest thing is to save the record in the DB, THEN you can select the record from the DB like:

record = SomeModel.last

and then use the two methods to create the range:

(record.project_start_date..project_end_date).each do |date|

Upvotes: 0

Related Questions