[SOLVED] Epoch timestamp to right date Time

Hi i am using this tho update a channel

                new DateTime (mower.getAttributes().getPlanner().getNextStartTimestamp()).toString()));

My problem is that the epoch timestamp is in UTC but when i do this i get it in my local timezone.
How can i update the the channel with UTC DateTime.


Output from epoch Online
Convert epoch to human-readable date and vice versa
GMT: Monday 13 July 2020 06:00:00
Your time zone: måndag 13 juli 2020 kl. 08:00:00 GMT+02:00 DST

It is the GMT time i want in the DateTime not my time zone.

May we see what this string looks like? Maybe you can just replace the tz with UTC


Did you try passing the string without wrapping it in a new DateTime?


(P.s. I assume DateTime is from org.joda.time, which you should not use anymore as it will not be supported in OH 3 as a standard library).

1 Like

As hilbrand says, with avoiding Joda datetime -

demo in a rule

val EpochString = "1594620000000"
// epoch carries no timezone info at all
// and so is usually assumed to be GMT aka UTC

// conventional conversion 
val MyDateTimeTypeFromEpoch = new DateTimeType(EpochString)
logInfo("test", "raw dttype " + MyDateTimeTypeFromEpoch.toString)

// post to Item
testDate.postUpdate(new DateTimeType(EpochString))
logInfo("test", "item " + testDate.state.toString)


2020-07-14 13:34:44.684 [INFO ] [.eclipse.smarthome.model.script.test] - raw dttype 2020-07-13T06:00:00.000+0000
2020-07-14 13:34:45.190 [INFO ] [.eclipse.smarthome.model.script.test] - item 2020-07-13T06:00:00.000+0000

I think that’s what you are after?

Thanks @hilbrand i am now using

        updateState(CHANNEL_STATUS_NEXTSTART_TIMESTAMP, new DateTimeType(Long.toString(mower.getAttributes().getPlanner().getNextStartTimestamp())));

and i get 2020-07-15T06:00:00.000+0000 and that is correct but the host saves everything in UTC and do not care about timezone.
So now when i display the channel in habpanel i get 2020-07-15T08:00:00.000+0200.
So i want to update the channel with 2020-07-15T06:00:00.000 and local timezone in my case +0200.


I’m not sure what you mean. But do you mean the number from NextStartTimestamp is NOT in UTC, but in the local time and when you put it in DateTimeType it is interpreted as UTC time. In other words the host does NOT save it in UTC but in local time, it just doesn’t tell which timezone it is in?

Yes it does not tell what timezone it is, but when i put an epoch timestamp into DateTimeType it assumes UTC.

That is the correct thing to do.

What is it that you want to happen instead? You want this timestamp to display in local time? Or you want it to be treated not as UTC, but as though it were some other timezone timestamp?

It’s more complicated than you might expect. In theory, the DateTime Item holds the timezone as well as the time. So when inputting UTC you get the Z zone, +0000.
It should be easy to adjust to the system default zone , which looks like +0200 DST for you. But this does not (yet) exist in the framework.

It’s something you’ll have to convert for yourself, which with summertime etc. is bit more complicated than just adding hours.
But first be clear about what you are trying to achieve.

Been having a play, in rules but principles should apply to binding code.

Three ways to “import” this timestamp -
(my timezone is BST +0100)

val EpochString = "1594620000000"
var EpochMillis = Long::parseLong(EpochString)

    // conventional conversion
    // Item gets true UTC value
val DTtypeFromEpoch = new DateTimeType(EpochString)
testDate.postUpdate(DTtypeFromEpoch.toString) // defaults to system zone

    // use if Epoch is really Epoch e.g. in UTC
    // offsets Item to local timezone
val corrZDT = java.time.ZonedDateTime.ofInstant(
            java.time.ZoneId.of(now.getZone.getID, java.time.ZoneId.SHORT_IDS)
testDate.postUpdate(corrZDT.toLocalDateTime.toString) // defaults to system zone

    // use if Epoch is pretend Epoch e.g.
    // assumes local zone without making offset
val ZDT = java.time.ZonedDateTime.ofInstant(
            java.time.ZoneId.of("UTC")   // stops any offset
testDate.postUpdate(ZDT.toLocalDateTime.toString) // defaults to system zone

new states

2020-07-15 02:35:51.595 [vent.ItemStateChangedEvent] - testDate changed ... to 2020-07-13T06:00:00.000+0000

2020-07-15 02:35:51.614 [vent.ItemStateChangedEvent] - testDate changed ... to 2020-07-13T07:00:00.000+0100

2020-07-15 02:35:51.631 [vent.ItemStateChangedEvent] - testDate changed ... to 2020-07-13T06:00:00.000+0100

Thanks @rossko57.

I was also testing and got this to work as i wanted

            Calendar utcTime = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
            Calendar localTime = Calendar.getInstance();

            for (int i = 0; i < Calendar.FIELD_COUNT; i++) {
                if( (i != Calendar.ZONE_OFFSET) && (i != Calendar.DST_OFFSET) ) { 
                localTime.set(i, utcTime.get(i));

            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
            updateState(CHANNEL_STATUS_NEXTSTART_TIMESTAMP, new DateTimeType(dateFormat.format(localTime.getTime())));

I dont know what are the prefered way.


It looks like the following code should also do what you want:

long timestamp = mower.getAttributes().getPlanner().getNextStartTimestamp();
ZonedDateTime zonedDateTime = ZonedDateTime.ofLocal(
                LocalDateTime.ofInstant(Instant.ofEpochMilli(timestamp), ZoneId.of("UTC")),
                ZoneId.systemDefault(), // Assuming this will give your systems local time zone
updateState(CHANNEL_STATUS_NEXTSTART_TIMESTAMP, new DateTimeType(zonedDateTime));
1 Like