The method getZonedDateTime() from the type DateTimeType is deprecated

I assume when something is deprecated it is on the list for removal in the not too distant future. A proactive approach is to fix the offending code. In my case that is what I did by replacing getZonedDateTime() with getInstant(), but I was unaware that plusMinutes and plusHours were not supported by Instant so there was a cascading effect in that many rules no longer worked and now had errors as I indicated in my previous post. Those errors were corrected using the generic plus(number,chrono.Unit).

While the example I gave doesn’t exactly fit within this thread, I have many that do. It was just quick to grab the code to illustrate the error I was seeing. Further if you don’t feel this is an issue then feel free to ignore it, but I spent the afternoon trying to resolve it and I am betting others will run into this as well.

Quite the opposite, I’m trying to understand how it relates, so I can figure out how to best approach it. Now you gave me that context when mentioning that you replaced getZonedDateTime() with getInstant() because of the deprecation - thanks. Whereas the Instant.now() example was confusing, because it didn’t seem to have anything to do with this.

Unfortunately I don’t think it’s possible to add anything to the deprecation notice itself. You mentioned the documentation - do you know of a page where something needs to be updated? Probably documentation is not the first place users will look, but if something is outdated now, it must be updated.

I have provided a note that will be displayed when upgrading:

CORE: The DateTimeType methods toZone(zone), toLocaleZone() and getZonedDateTime() have been deprecated. They will be removed in a future version. getZonedDateTime(ZoneId) or getInstant() can be used as replacements for getZonedDateTime().

Do you think getInstant() should not be mentioned here, since it’s not a direct replacement? Is that what lead you into replacing getZonedDateTime() with getInstant()? In that case the note should probably be further refined, since only getZonedDateTime(ZoneId) is a direct replacement.

If getZonedDateTime(ZoneId) maintains all of the time manipulation functions such as plusHours(), withHours(), etc, whereas getInstant() does not, then I would not mention getInstant(). This would then also not require any changes to the documentation or further warnings of breaking changes.

Hi,

I upgraded to OH 4.3 stable and replaced all getZonedDateTime() by getZonedDateTime(ZoneId.systemDefault()) as suggested in here as well as the docu.
Nevertheless, log output still tells me:

The method getZonedDateTime() from the type DateTimeType is deprecated

Is this correct (but irritating to me) behaviour?

Best

I think you mean oH 4.3.0.
(item.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault())
works without ā€œdeprecatedā€ message for me

This should only happen if you still have usages of getZonedDateTime() in your rules. Please note that referencing a DateTimeType by .zonedDateTime is also calling getZonedDateTime() behind the scenes.

Perhaps you could try to make a small change to one of your rules to see if the log output will appear. When you have located a rule or rule file causing the log output, can you post that rule in its entirety here?

If your rules are file-based you could also try to grep "getZonedDateTime()" and grep ".zonedDateTime" in your /etc/openhab/rules directory.

I corrected my typo and yes I mean OH 4.3 (not 3.4).
As I have text based files, I replaced all getZonedDateTime() by getZonedDateTime(ZoneId.systemDefault()). I expected everything is fixed then as I understood the change log.

I have a few .zonedDateTime functions as well but log shows me MUCH more of the same error messages in rules that do NOT use .zonedDateTime.

Examples of different lines of code attached:

FlurEGBewegungsmelderManuellerModus_Timer_Ende.sendCommand(ZonedDateTime.now.minusMinutes(1).toInstant.toEpochMilli  )
now.minusHours(3).isAfter(((RegensensorRegenEnde.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault())))
if (Duration.between((Stromzaehler_lastchange.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()), ZonedDateTime.now()).toSeconds() >= 3600) {
HomematicIP_Thermostat_BueroManuela_Profile_Override_EndDateTime.sendCommand(ZonedDateTime.now.minusMinutes(1).toInstant.toEpochMilli  )

Honestly: I always have been happy when I got a working code for time based code. Happy to improve my code.

I could imagine that a more specific hint of how to fix / change when migrating to OH 4.3 might help not only me.

Thanks

Your code works without ā€œdeprecatedā€ message on my installation.

Do you get this frontail message after oH resart?
2024-12-18 14:00:31.677 [INFO ] [org.openhab.core.Activator] - Starting openHAB 4.3.0 (Release Build)

What operating system does your OH run on and what version of Java do you use?

I saw this message even after replacing via getZonedDateTime(ZoneId.systemDefault()) on Openhabian after upgrading to OH 4.3

I changed then to docker with my old OH 4.2.2 as the upgrade was quite broken and I wanted to change to docker anyhow. After upgrading docker from OH 4.2.2 to OH 4.3 I got the same error, see above.

How can I see Java version used by docker?

Yes, I see this error only with frontail as the new OH logview is not available that ā€œearlyā€ (is this intended?)

I don’t know what ā€œallā€ means, I don’t know how your rule files are structured and I don’t know if you also have UI rules at the same time. In other words, I need more specific information. For example, if I create a file named rules/test.rules with this content:

rule "Test"
when
	Item Test changed to ON
then
    var zoned = (TestDateTime.state as DateTimeType).zonedDateTime
    logInfo("test", zoned.toString)
end

this is logged:

2024-12-18 21:38:37.679 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'test.rules', using it anyway:
The method getZonedDateTime() from the type DateTimeType is deprecated

If I then change the contents to:

rule "Test"
when
	Item Test changed to ON
then
    var zoned = (TestDateTime.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault)
    logInfo("test", zoned.toString)
end

and save, then this is logged:

2024-12-18 21:41:53.049 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'test.rules'

So I need you to isolate and reproduce the issue when saving a specific file with changes (to trigger reload) and provide:

  • The log lines when the rule is loaded.
  • The contents of the rule file in its entirety (you can PM me if you don’t feel confident sharing it publicly).

I.e. the story with all relevant details from the reproduction steps - like I did above.

For each file you change - if it doesn’t reproduce the issue, it’s not that file causing it, so you will need to continue until you find a file that does.

Hopefully this explains what I meant with:

And also you could post the results of:

1 Like

I have only file based rules, hence all (meaning all ;-)) getZonedDateTime() are replced by getZonedDateTime(ZoneId.systemDefault()).

.zonedDateTime still exists as I do not know how to replace correctly.

The errors are reproducable as soons as I re-save the file. I extracted code that causes the message:

rule "Test 1"
when
    Item testswitch changed
then
   val Number MyEpochFromDateTimeTypeItem = (newState as DateTimeType).zonedDateTime.toInstant.toEpochMilli
    DuschbadThermostat_Profile_Override_EndTimestamp.sendCommand(MyEpochFromDateTimeTypeItem / 1000)
end

Log:

2024-12-18 22:11:14.979 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'test1.rules'

2024-12-18 22:11:15.316 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'test1.rules', using it anyway:

The method getZonedDateTime() from the type DateTimeType is deprecated

Another rule (same filename just overwritten)

rule "Test 2"
when
    Item testswitch changed
then
   if ((Speedtest_LastUpdate.state as DateTimeType).zonedDateTime.toInstant.toEpochMilli < today_morning) {
        Speedtest_online.sendCommand(OFF)
    } else {
        Speedtest_online.sendCommand(ON)
    }
end
2024-12-18 22:13:45.826 [INFO ] [el.core.internal.ModelRepositoryImpl] - Loading model 'test1.rules'

2024-12-18 22:13:46.184 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'test1.rules', using it anyway:

The method getZonedDateTime() from the type DateTimeType is deprecated

Maybe as a first step I try to get rid of .zonedDateTime as you suggested and test further afterwords.

I doubled checked change log again and it is stated:

The DateTimeType methods toZone(zone), toLocaleZone() and getZonedDateTime() have been deprecated. They will be removed in a future version. In DSL rules, please use getZonedDateTime(ZoneId) as replacement for getZonedDateTime(), for example getZonedDateTime(ZoneId.systemDefault()) to use system time-zone.

So no hint for me to dig into .zonedDateTime nor why or even how to replace.

Any hint how to replace this?

Thanks!

As I already mentioned:

So this is the culprit and the reason why you are still using the deprecated method and seeing these deprecation warnings.

zonedDateTime is equivalent to getZonedDateTime(), and therefore you can replace it with getZonedDateTime(ZoneId.systemDefault) as well.

Now that you are at it, you could also simplify a few things, but you should do that as next step since it won’t by a simple ā€œsearch & replaceā€ operation.

This:

val Number MyEpochFromDateTimeTypeItem = (newState as DateTimeType).zonedDateTime.toInstant.toEpochMilli

Can be rewritten to:

val Number MyEpochFromDateTimeTypeItem = (newState as DateTimeType).instant.toEpochMilli

The message is correct. But I’ll admit that I only recently learned that .zonedDateTime can be used to access the void getter carrying that name, i.e. getZonedDateTime(). I’m almost at the end of rewriting all my DSL rules to JavaScript, so I didn’t have a big rule collection to test with and therefore only did the basic tests.

2 Likes

If you have multiple rules files and multiple rules in them, I would first deactivate them all and create a System started test rule with just a minimalist .getZonedDateTime(ZoneId.systemDefault()) statement to see if this warning really comes up. Then, you have a problem with the oH 4.3 installation. Otherwise, reactivate rule by rule to see which statements are causing the problem.

I followed the hint to replace also .zonedDateTime and actually replacing by the shorter code as well. => works now without warnings!

Changing to JS rules is on my plan anyhow.

Thank you all

1 Like

Hi,
I tried a lot with the new expressions e.g. time.toZDT(), but I can’t get the rules to work.
Could you please help me with following expression, which worked well till the OH upgrade, with the correct replacement?:

postUpdate(newtime, (oldtime.state as DateTimeType).zonedDateTime.minusMinutes(30).toString())

Thank you

postUpdate(newtime, (oldtime.state as DateTimeType).getZonedDateTime(ZoneId.systemDefault()).minusMinutes(30))

I’m also stuck on this same problem but with a small difference to all the other examples above. I fill a DateTimeType variable with the timestamp from a timeseries Item. I want to get the day / month / etc. from this variable but am unable to do so. Can anyone point me in the right direction? I tried for a couple of hours everything to get something out of the variable but the only way to display something from it is: 2025-02-24T21:30+01:00[Europe/Berlin]

var Number maxPower
var DateTimeType maxPowerTime

for (var i = 0; i < 24; i++) {
    val state = SolcastPowerEstimate.persistedState(now.minusHours(i))
    if (state !== null) {
        val numericValue = (state.state as QuantityType<Number>).floatValue() 
        if (numericValue > maxPower) {
            maxPower = numericValue
            maxPowerTime = state.timestamp
        }
    }
}

var formattedTime = (maxPowerTime as DateTimeType).getZonedDateTime(ZoneId.systemDefault()).getDayOfMonth

if (maxPowerTime !== null) {
    sendSmartHomeNotify.postUpdate("Hoogste vermogen in de afgelopen 24 uur: " + maxPower + " W om " + formattedTime)
} else {
    sendSmartHomeNotify.postUpdate("Geen waarden gevonden voor de afgelopen 24 uur.")
}

I declared formattedTime as datetimetype. I removed the ā€œas DateTimeTypeā€. I tried .Instant in several ways, and a dozen other things, but i just don’t understand how this works. I read the github page but have difficulty understanding that page. All other code regarding Datetime Items are working perfecly after applying ā€˜.getZonedDateTime(ZoneId.systemDefault())’ in stead of zoneddatetime. So the problem is just for the variables, but for what i’m building, I have to use the variables.

Try:

var formattedTime =time.toZDT(maxPowerTime).format(time.DateTimeFormatter.ofPattern("dd.MM. HH:mm:ss"));

or whatever part of the date you require.

EDIT:
Uh, just noticed you need DSL. My code is JS.
Maybe the easiest way is to use split if you only need day and month?

I was aware of split but it feels a bit funny, maybe that’s the easiest way but a function like getDayOfWeek makes a lot more sense.

As far as i can understand, there shouldn’t be to much difference between a DateTimeType variable and a DateTimeType Item in using it in a rule.

Finaly I found it! With a little help from ChatGPT:

var maxRecord = SMA_power.maximumSince(now.minusDays(1))
var int dayNumber = maxRecord.timestamp.getDayOfMonth()

I made a DateTimeType variable at first, but that’s wrong. Just put the item value it in a variable and I can use it as normal with getDayOfMonth(), etc.

Simple sollution, i’m happy and hoping someone could use this!