ramamoorthy_villi
ramamoorthy_villi

Reputation: 2055

exclude time from array of time - rails

Rails 5.x

This is an appointment system, displaying all the available time (steps) every 15 minutes.

start_time = '2:00 pm'.to_time

> 2020-10-26 14:00:00 +1100

and

end_time = '5:00 pm'.to_time
> 2020-10-26 17:00:00 +1100

I got the available time every 15mins

(start_time.to_i..end_time.to_i).to_a.in_groups_of(15.minutes).collect(&:first).collect { |t| Time.at(t) }  

[2020-10-26 14:00:00 +1100,
 2020-10-26 14:15:00 +1100,
 2020-10-26 14:30:00 +1100,
 2020-10-26 14:45:00 +1100,
 2020-10-26 15:00:00 +1100,
 2020-10-26 15:15:00 +1100,
 2020-10-26 15:30:00 +1100,
 2020-10-26 15:45:00 +1100,
 2020-10-26 16:00:00 +1100,
 2020-10-26 16:15:00 +1100,
 2020-10-26 16:30:00 +1100,
 2020-10-26 16:45:00 +1100,
 2020-10-26 17:00:00 +1100
] 

I want to exclude time which's not available. for eg:

2:30 to 3pm 

3:15 to 4pm 

any pretty way to fix this?

Upvotes: 1

Views: 79

Answers (1)

Ben Stephens
Ben Stephens

Reputation: 3371

Not sure this counts as pretty but ...

interval = 15.minutes
start_time = '2:00 pm'.to_time
end_time = '5:00 pm'.to_time

taken = [
    '2:30 pm'...'3:00 pm',
    '3:15 pm'...'4:00 pm'
]

def slots(start_time, end_time, interval)
    (start_time.to_i..end_time.to_i).
        to_a.
        in_groups_of(interval).
        collect(&:first).
        collect { |t| Time.at(t) }
end

def taken_slots(interval, taken)
    taken.collect { |r|
        slots(
            r.begin.to_time,
            r.end.to_time - (r.exclude_end? ? interval : 0),
            interval
        )
    }.flatten
end

def available_slots(start_time, end_time, interval, taken)
    slots(start_time, end_time, interval) - taken_slots(interval, taken)
end

available_slots(start_time, end_time, interval, taken)

gives

[
    2020-10-26 14:00:00 +0000,
    2020-10-26 14:15:00 +0000,
    2020-10-26 15:00:00 +0000,
    2020-10-26 16:00:00 +0000,
    2020-10-26 16:15:00 +0000,
    2020-10-26 16:30:00 +0000,
    2020-10-26 16:45:00 +0000,
    2020-10-26 17:00:00 +0000
]

I think if you needed to make slots faster the following miiiiight help (not tested though, and not sure what different values for interval might do)...

def slots(start_time, end_time, interval)
    ((start_time.to_i/interval)..(end_time.to_i/interval)).
        to_a.
        collect { |t| Time.at(t * interval) }
end

Edit:

The above faster slots seems to behave differently for different start and end times to how your original would, so maybe ignore that.

(example:)

interval = 15.minutes
start_time = '2:01 pm'.to_time
end_time = '5:00 pm'.to_time

def slots(start_time, end_time, interval)
    (start_time.to_i..end_time.to_i).
        to_a.
        in_groups_of(interval).
        collect(&:first).
        collect { |t| Time.at(t) }
end

def slots_f(start_time, end_time, interval)
    ((start_time.to_i/interval)..(end_time.to_i/interval)).
        to_a.
        collect { |t| Time.at(t * interval) }
end

slots(start_time, end_time, interval) =>

[
    2020-10-26 14:01:00 +0000,
    2020-10-26 14:16:00 +0000,
    2020-10-26 14:31:00 +0000,
    2020-10-26 14:46:00 +0000,
    2020-10-26 15:01:00 +0000,
    2020-10-26 15:16:00 +0000,
    2020-10-26 15:31:00 +0000,
    2020-10-26 15:46:00 +0000,
    2020-10-26 16:01:00 +0000,
    2020-10-26 16:16:00 +0000,
    2020-10-26 16:31:00 +0000,
    2020-10-26 16:46:00 +0000
]

slots_f(start_time, end_time, interval) =>

[
    2020-10-26 14:00:00 +0000,
    2020-10-26 14:15:00 +0000,
    2020-10-26 14:30:00 +0000,
    2020-10-26 14:45:00 +0000,
    2020-10-26 15:00:00 +0000,
    2020-10-26 15:15:00 +0000,
    2020-10-26 15:30:00 +0000,
    2020-10-26 15:45:00 +0000,
    2020-10-26 16:00:00 +0000,
    2020-10-26 16:15:00 +0000,
    2020-10-26 16:30:00 +0000,
    2020-10-26 16:45:00 +0000,
    2020-10-26 17:00:00 +0000
]

Upvotes: 1

Related Questions