Time Comparison Reliability


(Ronny Carr) #1

I have noticed that when using a smartapp that compares the current time to a user specified time, the results are not always what would be expected. Things that are scheduled for a specific time seem to work as intended. However, in my arrival smartapp for example, I have user specified times for what mode to set the apartment to when I arrive. This is really unreliable, as most of the time it sets to the wrong mode because it looks like the time that is returned from now() is wrong.

Really my main question is, has anyone else seen issues with the now() method and the time it returns while comparing it to a user defined time?


(Dan Lieberman) #2

Ronny –

How exactly are you doing the time comparison? If you can post your code here or email it to support@smartthings.com, we’ll try and help you figure it out.

Thanks!
-d


(Ronny Carr) #3

This is the method I’m using to control what mode to change to based on current time of day when I arrive. Thanks for the help in advance!

def arrivalControl() {
  def homeMode
  def currTime = now()
  def time1f = timeToday(time1) //morning start time
  def time2f = timeToday(time2) //afternoon start time
  def time3f = timeToday(time3) //evening start time
  def time4f = timeToday(time4) //night start time

  if (currTime > time4f.time || currTime < time1f.time){homeMode = modeH4} //it's night
  else if (currTime > time3f.time){homeMode = modeH3} //it's evening
  else if (currTime > time2f.time){homeMode = modeH2} //it's afternoon
  else if (currTime > time1f.time){homeMode = modeH1} //it's morning

  if (location.modes?.find{it.name == homeMode}) {
    lock1.unlock()
    sendPush("Changing mode to ${homeMode}, welcome back!")
    setLocationMode(homeMode)
  }
}

(Bob Florian) #4

Hi Ronny,

I think what you’re seeing is caused by a bug in the timeToday() function. If your night start time is 11:00 PM EDT, that’s 3:00 AM the next day UTC. So if you run timeToday on 6/14 it should be return 3:00 AM on 6/15, but its not. It’s incorrectly returning 3:00 AM on 6/14.

We’ll have the fix for this problem released next week.

Thanks,
Bob


(Ronny Carr) #5

I thought it may have something to do with time zones. They are hard. Looking forward to the fix, thanks for the help guys!


(Stephanschulz) #6

hi

i am too trying to see if the current time is within a set start and end time of day.

here part of the code:

preferences {
	section("Turn on when there's movement..."){
		input "motion1", "capability.motionSensor", title: "Where?"
        input "timeBegin", "time", title: "Time of Day to start"
        input "timeEnd", "time", title: "Time of Day to stop"
	}
	section("And off when there's been no movement for..."){
		input "minutes1", "number", title: "Minutes?"
	}
	section("Turn on/off light(s)..."){
		input "switches", "capability.switch", multiple: true
	}
}

def installed() {
	subscribe(motion1, "motion", motionHandler)
}

def updated() {
	unsubscribe()
	subscribe(motion1, "motion", motionHandler)
}

def motionHandler(evt) {
	log.debug "$evt.name: $evt.value"
   
    def currTime = now()
    def timeOfDay_begin = timeToday(timeBegin)
    def timeOfDay_end = timeToday(timeEnd)
    
    log.debug now()
    log.debug timeOfDay_begin
    log.debug timeOfDay_end
    
    //http://build.smartthings.com/forums/topic/comparing-current-time-with-input-time/
    //if current time is equal to or after user's time
	if(currTime >= timeOfDay_begin.time && currTime <= timeOfDay_end){
        if (evt.value == "active") {
            log.debug "turning on lights"
            switches.on()
        } else if (evt.value == "inactive") {
            runIn(minutes1 * 60, scheduleCheck, [overwrite: false])
        }
    }
}

but this is what the log spits out:
8:43:48 PM EST: error java.util.Date cannot be cast to java.lang.Long
8:43:48 PM EST: debug Wed Feb 05 16:04:00 UTC 2014
8:43:48 PM EST: debug Wed Feb 05 07:04:00 UTC 2014
8:43:48 PM EST: debug 1391651028717

can i not compare now() with a set time?

thanks.


(Ronny Carr) #7

Looks like you need to add .time to timeOfDay_end in your first if statement. That could be it, but nothing else jumps out at me.


(Stephanschulz) #8

you are right i noticed that just now too.

i am also learning that i will have to add 246060*1000 to my end time, since it is for the next day.

thanks again


(Stephanschulz) #9

i got it to work.
i thought i had to offset the end time so that is knows it’s the next day, but i did not.
also did not have to worry about UTC time, seems smartthings knows what my local time is.

preferences {
	section("Turn on when there's movement..."){
		input "motion1", "capability.motionSensor", title: "Where?"
        input "timeBegin", "time", title: "Time of Day to start"
        input "timeEnd", "time", title: "Time of Day to stop"
        input "timeOffset", "number", title: "Coordinated Universal Time offset"
        
	}
	section("And off when there's been no movement for..."){
		input "minutes1", "number", title: "Minutes?"
	}
	section("Turn on/off light(s)..."){
		input "switches", "capability.switch", multiple: true
	}
}

def installed() {
	subscribe(motion1, "motion", motionHandler)
}

def updated() {
	unsubscribe()
    
    
    
    def currTime = now()
     def currTime5 = currTime + 5*60*60*1000
    def timeOfDay_begin = timeToday(timeBegin)
    def timeOfDay_end = timeToday(timeEnd) 
    
    def timeOfDay_end_plus24hours = timeOfDay_end.time+ 24*60*60*1000
    
    def timeOfDay_begin5 = timeOfDay_begin.time - 5*60*60*1000  
    def timeOfDay_end5 = timeOfDay_end.time - 5*60*60*1000
    
    log.debug "currTime     $currTime   $currTime5"
    log.debug "timeOfDay_begin.time   $timeOfDay_begin.time    $timeOfDay_begin5"
    log.debug "timeOfDay_end.time    $timeOfDay_end.time    $timeOfDay_end5"
    
    
    log.debug "timeOfDay_begin   $timeOfDay_begin"
    log.debug "timeOfDay_end   $timeOfDay_end"
    
    if(currTime >= timeOfDay_begin.time) log.debug "currTime >= timeOfDay_begin.time"
    if(currTime <= timeOfDay_end.time) log.debug "currTime <= timeOfDay_end.time"
    
    if(currTime >= timeOfDay_begin.time || currTime <= timeOfDay_end.time){
    log.debug "should work"
    }
    
    if(currTime >= timeOfDay_begin5 || currTime <= timeOfDay_end5){
    log.debug "555 should work  $timeOffset"
    }
    
	subscribe(motion1, "motion", motionHandler)
}

def motionHandler(evt) {
	log.debug "$evt.name: $evt.value"
  
     def message = "motion detected"
			log.info message
          //  send(message)
            
    def currTime = now()
    def currTime5 = currTime + 5*60*60*1000
    def timeOfDay_begin = timeToday(timeBegin)
    def timeOfDay_end = timeToday(timeEnd)
    def timeOfDay_end_plus24hours = timeOfDay_end.time+ 24*60*60*1000
    
    log.debug currTime
    log.debug timeOfDay_begin.time
    log.debug timeOfDay_end_plus24hours
    
    def timeOfDay_begin_UTCoffset = timeOfDay_begin.time - timeOffset*60*60*1000
    def timeOfDay_end_plus24_UTCoffset = timeOfDay_end_plus24hours - timeOffset*60*60*1000
    
    
    //http://build.smartthings.com/forums/topic/comparing-current-time-with-input-time/
    //if current time is equal to or after user's time
	if(currTime >= timeOfDay_begin.time || currTime <= timeOfDay_end.time){ //timeOfDay_end_plus24hours){
    //  if(currTime5 >= timeOfDay_begin5 || currTime <= timeOfDay_end5){
      if (evt.value == "active") {
            log.debug "turning on lights"
            switches.on()
        } else if (evt.value == "inactive") {
            runIn(minutes1 * 60, scheduleCheck, [overwrite: false])
        }
    }
    
}

def scheduleCheck() {
	log.debug "schedule check"
	def motionState = motion1.currentState("motion")
    if (motionState.value == "inactive") {
        def elapsed = now() - motionState.rawDateCreated.time
    	def threshold = 1000 * 60 * minutes1 - 1000
    	if (elapsed >= threshold) {
            log.debug "Motion has stayed inactive long enough since last check ($elapsed ms):  turning lights off"
            switches.off()
    	} else {
        	log.debug "Motion has not stayed inactive long enough since last check ($elapsed ms):  doing nothing"
        }
    } else {
    	log.debug "Motion is active, do nothing and wait for inactive"
    }
}

private send(msg) {
	if ( sendPushMessage != "No" ) {
		log.debug( "sending push message" )
		sendPush( msg )
	}

	if ( phone ) {
		log.debug( "sending text message" )
		sendSms( phone, msg )
	}

	log.debug msg
}