DateTime shows different results in rule

When using this code in a rule:

import org.joda.time.DateTime

rule "Test"
when
  Time cron "0 */1 * * * ?"
then
  var DateTime dt1 = now
  var DateTime dt2 = Weather_LastUpdate.state // any DateTime item

  logInfo("Test", ""+dt1)
  logInfo("Test", ""+dt2)

end

the output shows something like:

2017-01-11T00:00:00.000+01:00
2017-01-11T00:00:00.000+0100

As you may notice the timezone notation is different.
I have found that comparing these with (dt1 == dt2) will NEVER return true. Although they are equal, I guess.

Is this a bug or should I use some additional statement?

cc @rlkoshak @watou

In the rule above, now is a org.joda.time.DateTime, but Weather_LastUpdate.state is an openHAB/ESH DateTimeType. That’s why they print differently and why they will never be equal. Time comparisons when using classes of different sources is complicated unfortunately, but there are many examples of successful approaches.

Once ESH is using Java 8 as a minimum version, effort can be made to harmonize the situation and obsolete org.joda.time.

This used to work in OH1. This is the use case. My gas meter sends a reading every hour at the full hour. I capture this with the DSMR binding.
Once a day, at midnight, I publish the reading to www.mindergas.nl.

A rule compares the gas meter time stamp (00:00) with the current time converted to start of day. If true it is published.

I will post the OH1 rule tonight.

This code has been working flawlessly for about a year with OH1 and doesn’t in OH2:

/* utilities.rules */

import org.openhab.core.library.types.*
import org.openhab.core.persistence.*
import org.openhab.model.script.actions.*
import org.joda.time.*

rule Gas_Midnight
when
	Item P1_Gas_Timestamp changed
then
	logDebug("gas.midnight", "Gas Timestamp changed")
	var dt = parse(P1_Gas_Timestamp.state.toString)
	if (dt == now.toLocalDate.toDateTimeAtStartOfDay) {
		logDebug("gas.midnight", "Received gas meter reading for midnight.")
		callScript("mindergas")
	} else {
		logDebug("gas.midnight", "Received gas meter reading during the day.")
	}
end

Still no change in results. I have applied the suggestion from @rlkoshak to use equals and will see what happened tomorrow morning (I will be asleep at midnight :wink:).

No success. The rule never returns TRUE

Current rule

/* mindergas.rules */

import org.joda.time.DateTime

/* 
 * De slimme meter geeft 1x per uur een nieuwe stand van de gasmeter door. 
 * Een paar minuten na het hele uur ontvang je de stand per het hele uur.
 * Publiceer deze stand naar mindergas als de stand eind vorige dag.
 */
rule GasMeterChanged
when
	// Time cron "*/10 * * * * ?" or
	Item P1_Gas_Timestamp changed
then
	logInfo("GasMeterChanged", "Gas meter reading changed")

	var DateTime dtRun = parse(P1_Gas_Timestamp.state.toString)
	var DateTime dtSOD = now.toLocalDate.toDateTimeAtStartOfDay

	logInfo("GasMeterChanged", "Timestamp   : " + dtRun)
	logInfo("GasMeterChanged", "Start of day: " + dtSOD)

	if (dtRun.equals(dtSOD)) {
		logInfo("GasMeterChanged", "Gas meter reading changed at midnight.")
		callScript("mindergas")
	} else {
		logInfo("GasMeterChanged", "Gas meter reading changed during the day.")
	}
end

Logging:

2017-01-24 23:05:32.165 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-24 23:05:32.184 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp   : 2017-01-24T23:00:00.000+01:00
2017-01-24 23:05:32.192 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-24T00:00:00.000+01:00
2017-01-24 23:05:32.200 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
...
2017-01-25 00:05:28.544 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-25 00:05:28.563 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp   : 2017-01-25T00:00:00.000+01:00
2017-01-25 00:05:28.571 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-25T00:00:00.000+01:00
2017-01-25 00:05:28.580 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
...
2017-01-25 01:05:26.830 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-25 01:05:26.847 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp   : 2017-01-25T01:00:00.000+01:00
2017-01-25 01:05:26.856 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-25T00:00:00.000+01:00
2017-01-25 01:05:26.862 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.

Added these lines to the rule for further debugging:

	// Added additional equations from the Joda time documentation
	logInfo("GasMeterChanged", "==       : " + (dtRun == dtSOD))
	logInfo("GasMeterChanged", "equals   : " + dtRun.equals(dtSOD))
	logInfo("GasMeterChanged", "isEqual  : " + dtRun.isEqual(dtSOD))
	logInfo("GasMeterChanged", "compareTo: " + (dtRun.compareTo(dtSOD)==0))

To check a time is equal to, greater than, less than or within a range I use string comparisons, it is so much simpler.

In a datetime string, the time is located at positions 11-15 (10:45), in an Item declared as a string, it is located at positions 0-4. A range example would be:

   var hw1on = Hot_Water_1_On.state.toString    // time at position 0-4 (String Item set to "07:00" in startup rule)
   var hw1off = Hot_Water_1_Off.state.toString  
   var time1   = CurrentTime.state.toString     // time at position 11-15

   if ( time1.substring(11,16) >= hw1on.substring(0,5) && time1.substring(11,16) <= hw1off.substring(0,5)){
		     	        WITHIN TIMEBAND  
   }

or
   var time1   = CurrentTime.state.toString     // time at position 11-15
   if (time1.substring(11,16) >= "07:00" && time1.substring(11,16) <= "09:30"){
       WITHIN TIMEBAND  
   }

You example where you need to check the time is “00:00” would be:

rule Gas_Midnight
when
	Item P1_Gas_Timestamp changed
then
	logDebug("gas.midnight", "Gas Timestamp changed")
	var dt = P1_Gas_Timestamp.state.toString
	if (dt.substring(11,16)=="00:00") {
		logDebug("gas.midnight", "Received gas meter reading for midnight.")
		callScript("mindergas")
	} else {
		logDebug("gas.midnight", "Received gas meter reading during the day.")
	}
end

It also has the advantage that you can change the time to say “18:00” to test the rule rather than wait until midnight.

The technique can also be used for dates.

Thanks for your suggestion. I will try this if everything else fails. If so, I would use the whole string e.g. (dtRun.toString == dtSOD.toString) and not just the time part.

This is what happened last night with my additional tests:

2017-01-25 23:04:46.097 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-25 23:04:46.122 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp   : 2017-01-25T23:00:00.000+01:00 millis 1485381600000
2017-01-25 23:04:46.134 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-25T00:00:00.000+01:00 millis 1485298800000
2017-01-25 23:04:46.140 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
2017-01-25 23:04:46.153 [INFO ] [arthome.model.script.GasMeterChanged] - ==        : false
2017-01-25 23:04:46.161 [INFO ] [arthome.model.script.GasMeterChanged] - equals    : false
2017-01-25 23:04:46.169 [INFO ] [arthome.model.script.GasMeterChanged] - isEqual   : false
2017-01-25 23:04:46.185 [INFO ] [arthome.model.script.GasMeterChanged] - compareTo : false
2017-01-25 23:04:46.198 [INFO ] [arthome.model.script.GasMeterChanged] - millis    : false

2017-01-26 00:04:32.580 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-26 00:04:32.602 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp   : 2017-01-26T00:00:00.000+01:00 millis 1485385200000
2017-01-26 00:04:32.615 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-26T00:00:00.000+01:00 millis 1485385200000
2017-01-26 00:04:32.621 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
2017-01-26 00:04:32.634 [INFO ] [arthome.model.script.GasMeterChanged] - ==        : false
2017-01-26 00:04:32.642 [INFO ] [arthome.model.script.GasMeterChanged] - equals    : false
2017-01-26 00:04:32.649 [INFO ] [arthome.model.script.GasMeterChanged] - isEqual   : true
2017-01-26 00:04:32.663 [INFO ] [arthome.model.script.GasMeterChanged] - compareTo : true
2017-01-26 00:04:32.679 [INFO ] [arthome.model.script.GasMeterChanged] - millis    : true

2017-01-26 01:04:30.292 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed
2017-01-26 01:04:30.325 [INFO ] [arthome.model.script.GasMeterChanged] - Timestamp   : 2017-01-26T01:00:00.000+01:00 millis 1485388800000
2017-01-26 01:04:30.342 [INFO ] [arthome.model.script.GasMeterChanged] - Start of day: 2017-01-26T00:00:00.000+01:00 millis 1485385200000
2017-01-26 01:04:30.352 [INFO ] [arthome.model.script.GasMeterChanged] - Gas meter reading changed during the day.
2017-01-26 01:04:30.368 [INFO ] [arthome.model.script.GasMeterChanged] - ==        : false
2017-01-26 01:04:30.380 [INFO ] [arthome.model.script.GasMeterChanged] - equals    : false
2017-01-26 01:04:30.389 [INFO ] [arthome.model.script.GasMeterChanged] - isEqual   : false
2017-01-26 01:04:30.405 [INFO ] [arthome.model.script.GasMeterChanged] - compareTo : false
2017-01-26 01:04:30.419 [INFO ] [arthome.model.script.GasMeterChanged] - millis    : false

3 of the new equations returned true! I have already changed the rule to use isEqual and will monitor in the coming days.

Last night the rule triggered the script. So the isEqual is working. I will simplify the rule code and post a working example for later reference by the community.