DateTimeType and timezones

(Anders Alfredsson) #1

I know there has been threads concerning this issue before, but openHAB’s (or ESH’s) DateTimeType doesn’t seem do work well with timezones.

I have a rule which gets JSON data witch includes a timestamp in UTC. I did some tests to illustrate the problem:

		val DateTime lastActivity = new DateTime(transform("JSONPATH", "$.lastActivityDate", output))
		val DateTimeType test1 = new DateTimeType(transform("JSONPATH", "$.lastActivityDate", output))
		val Date test2 = new Date(lastActivity.millis)
		logInfo("Test", "JSON output:   " + transform("JSONPATH", "$.lastActivityDate", output))
		logInfo("Test", "Joda DateTime: " + lastActivity.toString)
		logInfo("Test", "DateTimeType:  " + test1.toString)
		logInfo("Test", "Java Date:     " + test2.toString)
		logInfo("Test", "Joda DateTime millis: " + lastActivity.millis.toString)
		logInfo("Test", "DateTimeType millis:  " + test1.calendar.timeInMillis.toString)

This outputs:

2017-08-10 15:32:31.890 [INFO ] [.eclipse.smarthome.model.script.Test] - JSON output:   2017-08-10T13:31:33Z
2017-08-10 15:32:31.896 [INFO ] [.eclipse.smarthome.model.script.Test] - Joda DateTime: 2017-08-10T15:31:33.000+02:00
2017-08-10 15:32:31.903 [INFO ] [.eclipse.smarthome.model.script.Test] - DateTimeType:  2017-08-10T13:31:33.000+0200
2017-08-10 15:32:31.909 [INFO ] [.eclipse.smarthome.model.script.Test] - Java Date:     Thu Aug 10 15:31:33 CEST 2017
2017-08-10 15:32:31.915 [INFO ] [.eclipse.smarthome.model.script.Test] - Joda DateTime millis: 1502371893000
2017-08-10 15:32:31.922 [INFO ] [.eclipse.smarthome.model.script.Test] - DateTimeType millis:  1502364693000

The DateTimeType appears to always treat the timestring as local time, so it subtracts the time offset before it stores the value even if the string explicitely states it is Zulu-time (UTC).

I have solved the issue with a workaround:

		val DateTime lastActivity = new DateTime(transform("JSONPATH", "$.lastActivityDate", output))
		Heatpump_LastActivity.postUpdate(new DateTimeType(lastActivity.toString))

But is this really how it should work?

(Udo Hartmann) #2

(Anders Alfredsson) #3

I have read that, and as I wrote I have a workaround. My question was regarding the inner workings of the DateTimeType, especially when parsing a string, since it obviously doesn’t handle it in the same way as Joda DateTime. My question is if there is a reason it disregards the timezone and always assume local time, or if this is an oversight in the implementation, that should be corrected.

For reference I tried replacing the “Z” with “+0200”, but with the same result, so it seems like it doesn’t take that part of the string into account, when parsing it.

Edit: I realized that setting “+0200” is supposed to produce the same value as using local time. When I instead changed it to “+0000” it set the correct time! So it would seem that it doesn’t recognize the “Z” to mean UTC, and instead interpret it as local time. Should this be reported as a bug?

Edit2: After looking at the ESH sourcecode for the DateTimeType and made some more tests i’ve come to the following hypothesis:
When parsing a datestring, four different formats are tested against.

    public static final String DATE_PATTERN = "yyyy-MM-dd'T'HH:mm:ss";
    public static final String DATE_PATTERN_WITH_TZ = "yyyy-MM-dd'T'HH:mm:ssz";
    public static final String DATE_PATTERN_WITH_TZ_AND_MS = "yyyy-MM-dd'T'HH:mm:ss.SSSZ";
    public static final String DATE_PATTERN_WITH_TZ_AND_MS_ISO = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

When testing different formats:

  1. 2017-08-10T17:59:33+0000 - Works
  2. 2017-08-10T17:59:33.000Z - Works
  3. 2017-08-10T17:59:33Z - Doesn’t work.

1 gets matched by DATE_PATTERN_WITH_TZ
3 gets matched by DATE_PATTERN, because the “Z” is only recognized by “ISO 8601 Time zone” (X in SimpleDateFormat) and therefore discarded and no timezone is applied.

The solution would be to add

    public static final String DATE_PATTERN_WITH_TZ_ISO = "yyyy-MM-dd'T'HH:mm:ssX";

to the list of valid date formats in the DateTimeType class.

@Kai, am I correct?

(Anders Alfredsson) #4

Revisiting this thread since I noticed an inconsistecy in the parsing of datetime strings. If i update an item using the REST API with the string 2018-02-13T15:13:59Z the item gets the state 2018-02-13T15:13:59.000+0000 wihch is correct.

However when the item receives the same string through mqtt the state changes to 2018-02-13T15:13:59.000+0100 which is the wrong timezone (the Z at the end means UTC, so the time offset should be +0000

Is the REST API doing it’s own parsing of the string?