Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Time-of-day range in Ruby?

Tags:

time

ruby

I want to know if a time belongs to an schedule or another.

In my case is for calculate if the time is in night schedule or normal schedule.

I have arrived to this solution:

NIGHT = ["21:00", "06:00"]
def night?( date )
  date_str = date.strftime( "%H:%M" )
  date_str > NIGHT[0] || date_str < NIGHT[1]
end

But I think is not very elegant and also only works for this concrete case and not every time range.

(I've found several similar question is SO but all of them make reference to Date ranges no Time ranges)

Updated

Solution has to work for random time ranges not only for this concrete one. Let's say:

"05:00"-"10:00"
"23:00"-"01:00"
"01:00"-"01:10"
like image 820
fguillen Avatar asked Apr 06 '12 15:04

fguillen


2 Answers

This is actually more or less how I would do it, except maybe a bit more concise:

def night?( date )
    !("06:00"..."21:00").include?(date.strftime("%H:%M"))
end

or, if your schedule boundaries can remain on the hour:

def night?(date)
    !((6...21).include? date.hour)
end

Note the ... - that means, basically, "day time is hour 6 to hour 21 but not including hour 21".

edit: here is a generic (and sadly much less pithy) solution:

class TimeRange
    private

    def coerce(time)
        time.is_a? String and return time
        return time.strftime("%H:%M")
    end

    public

    def initialize(start,finish)
        @start = coerce(start)
        @finish = coerce(finish)
    end

    def include?(time)
        time = coerce(time)
        @start < @finish and return (@start..@finish).include?(time)
        return !(@finish..@start).include?(time)
    end
end

You can use it almost like a normal Range:

irb(main):013:0> TimeRange.new("02:00","01:00").include?(Time.mktime(2010,04,01,02,30))
=> true
irb(main):014:0> TimeRange.new("02:00","01:00").include?(Time.mktime(2010,04,01,01,30))
=> false
irb(main):015:0> TimeRange.new("01:00","02:00").include?(Time.mktime(2010,04,01,01,30))
=> true
irb(main):016:0> TimeRange.new("01:00","02:00").include?(Time.mktime(2010,04,01,02,30))
=> false

Note, the above class is ignorant about time zones.

like image 128
Michael Slade Avatar answered Sep 19 '22 12:09

Michael Slade


In Rails 3.2 it has added Time.all_day and similars as a way of generating date ranges. I think you must see how it works. It may be useful.

like image 42
drr Avatar answered Sep 19 '22 12:09

drr