How to use timeOfDayIsBetween() when end time is after 12am, that is +1 day later?

Hi everybody,

I have hard coded a solution to my problem but I am posting this to see if there's a better way to achieve the same result.

The idea is to set a time window between, for example, 7 pm and 8am the next day. If I simply use timeOfDayIsBetween(), it doesn't work, unless I use groovy.time.TimeCategory as seen below.

Please, let me know if you know a simpler way to do this.

boolean restrictedTime(){

    result = false    
    if(!restrictedTimeSlots) result = false 

    if(atomicState.timeSlots){
        int s = atomicState.timeSlots
        for(int i = 0; i < s; i++){

            def start = settings.find{it.key == "restrictedTimeStart${i}"}.value            
            def end = settings.find{it.key == "restrictedTimeEnd${i}"}.value

            def nextD = settings.find{it.key == "plusOneDay${i}"}?.value 
            if(nextD) {
                def nEnd = Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", end) //time must be re-parsed into date format using proper pattern  "2022-11-21T08:00:00.000-0500" 

                use(groovy.time.TimeCategory) {
                    logging "current time: ${new Date().format('yyyy-MM-dd h:mm:ss')}"
                    logging "mode: $location.currentMode"
                    nextday = nEnd + 1.day  
                    end = nextday.format("yyyy-MM-dd'T'HH:mm:ss.SSSZ")                    
                }
            }

            logging "start time slot #$i: ${Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ",start) }"
            logging "end time slot #$i: ${Date.parse("yyyy-MM-dd'T'HH:mm:ss.SSSZ", end)} ${nextD ? "(+1 day)" : ""}"

            def test = timeOfDayIsBetween(toDateTime(start), toDateTime(end), new Date(), location.timeZone)
            if(test) result = true
        }
    }

    log.debug "restricted time returns $result"
    return result
}

Here are a few ideas for you:

First, for your start and end values, it's much easier to just do this, instead of .find:

def starting = settings["restrictedTimeStart${i}"]      
def ending = settings["restrictedTimeEnd${i}"]

Settings is a map and you can reference into it directly with the key, rather than searching for the key.

Next thing is, if these were inputs of type "time", then instead of using timeOfDayIsBetween(), you could do this, returning the final value as the Boolean:

def currTime = now()
start = timeToday(starting, location.timeZone).time
stop = timeToday(ending, location.timeZone).time
return start < stop ? currTime >= start && currTime <= stop : currTime <= stop || currTime >= start

That covers the case of spanning midnight.

2 Likes

Indeed... :slight_smile: Dunno why I never thought about just calling the map's value... Must be because I learned to do it this way long before I understood maps' syntax and then it became muscle memory. Thanks for the refresher!

Thanks a lot, also, for the solution! I felt I was missing something about comparing times as quantitative instances (MS long integer, I suppose) but I got lost in figuring out Date/Strings conversions instead.

I'll implement your solution after I am done with today's coding classes! :sweat_smile:

Have a great day and Happy Thanksgiving!

In webcore, sometimes I find it easier to do the opposite: If time is NOT between the end time and start time, then do stuff. By putting the end time before the start time and using NOT, it ensures both times are part of the same day.

1 Like

Download the Hubitat app