Get Time Period on System Start Failing due to getCalendar()

It appears getCalendar() is now deprecated?

The method getCalendar() from the type DateTimeType is deprecated

Any ideas how I might tweak this rule?

rule "Get time period for right now"
when
System started
then
logInfo(“EXTRA”, “System started, attempting to get time period for right now”)
val now = new Date()
val dawn = new Date((DawnStart_Time.state as DateTimeType).calendar.timeInMillis)
val day = new Date((DayStart_Time.state as DateTimeType).calendar.timeInMillis)
val dusk = new Date((DuskStart_Time.state as DateTimeType).calendar.timeInMillis)
val night = new Date((NightStart_Time.state as DateTimeType).calendar.timeInMillis)

val String initStr = "Initializing time period. The time of day is "

See my response in the other thread.

The tl;dr for the rest of the users:

This shows a better approach than creating a bunch of new Date objects.

After updating my OH from #1078 to the latest 2.2 I got an error, too:

postUpdate(Sunset, new DateTimeType(DateString))

throws a

2017-12-06 21:20:11.048 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule 'Sun Calculations': 2017-12-6T7:59:00 is not in a valid format.

Could this be the same problem?

Michael

No, that is something else. It should be able to process that String though. At least it looks like the supported value.

Try logging Sunset.state.toString and DateString and see if they are formatted the same. You can try just passing DateString itself since postUpdate(itemanme, newstate) only takes a String anyway. This means that your new DateTimeType is redundant as you create a DateTimeType with a String and then in the background it gets converted back into a String before being sent to Sunset where it is converted back into a DateTimeType. This is one of the reason I strongly recommend always using the postUpdate method on the Item instead.

Sunset.postUpdate(DateString)

Thank you, @rlkoshak
I could not locate the error exactly - but it was possible to remove the Sunset in that function…

Thanks @rlkoshak (as always!).

No matter what I try though, I still get;

The method getCalendar() from the type DateTimeType is deprecated

Well, deprecation is just a warning so for the short run you can just ignore it.

I’m not seeing that warning but I’m on an older build of the snapshot. The method is not marked as deprecated in the JavaDoc, aha, but I see now it is marked as deprecated in the code.

Looks like they switched from using a regular old Date to a ZonedDateTime object.

So use:

 (Sunset.state as DateTimeType).toEpochSecond * 1000

to get the same behavior without the deprecation warnings.

Let me know if that works, it is all theoretical since I can’t try it on my system.

I think I’ve nixed my setup again after updating the snapshot to 1114 it won’t get beyond Loading UI again. Grre

So it wasn’t dead after all - thankfully. Just gremlins.

After altering the Astro 2.0 example you provided, I’m still getting the same issues.

The method getCalendar() from the type DateTimeType is deprecated

rule "Calculate time of day state"
when
    System started or
	Channel 'astro:sun:local:civilDawn#event' triggered START or // Dawn start
    Channel 'astro:sun:local:rise#event' triggered END or  // (Sunrise) Day start
	Channel 'astro:sun:local:civilDusk#event' triggered START or // Civil Dusk with -120 offset, starts to get dark from here
    Channel 'astro:sun:local:set#event' triggered START or // Dusk (Sunset) start
	Channel 'astro:sun:local:eveningNight#event' triggered START or // Evening start
	Channel 'astro:sun:local:morningNight#event' triggered START or // Night start
	Time cron "0 0 6,23,0 * * ? *" // there is currently a bug where only one cron is triggered per rule so I've combined all three into one
then
  Thread::sleep(1000) // make sure we are a tad past midnight to give Astro a chance to recalculate DateTimes for today

  val long morning_start = now.withTimeAtStartOfDay.plusHours(6).millis
  val long day_start = (DayStart_Time.state as DateTimeType).toEpochSecond * 1000
  val long afternoon_start = (TwilightStart_Time.state as DateTimeType).toEpochSecond * 1000
  val long evening_start = (DuskStart_Time.state as DateTimeType).toEpochSecond * 1000
  val long night_start = now.withTimeAtStartOfDay.plusHours(23).millis
  val long bed_start = now.withTimeAtStartOfDay.millis

  var curr = "UNKNOWN"

  switch now {
        case now.isAfter(morning_start) && now.isBefore(day_start):       curr = "MORNING"
        case now.isAfter(day_start) && now.isBefore(afternoon_start):     curr = "DAY"
        case now.isAfter(afternoon_start) && now.isBefore(evening_start): curr = "AFTERNOON"
        case now.isAfter(evening_start) && now.isBefore(night_start):     curr = "EVENING"
        case now.isAfter(night_start):                                    curr = "NIGHT"
        case now.isAfter(bed_start) && now.isBefore(morning_start):       curr = "BED"
  }

  if(TimePeriodOfDay.state.toString != curr) {
    logInfo("EXTRA", "Current time of day is now " + curr)
    TimePeriodOfDay.sendCommand(curr)
  }

end

Are you sure it is coming from this Rule? You are not calling calendar or getCalendar anywhere in this Rule. So either the warning is coming from some other Rule or from code that is outside your control.

My bad/apologies, shortly after writing my last response I went off to hospital to have a child :smiley:

Revisiting this now, with a bit more focus and clarity (only a bit mind!), the log shows;

2017-12-10 06:00:01.063 [ERROR] [ntime.internal.engine.ExecuteRuleJob] - Error during the execution of rule ‘Calculate time of day state’: ‘toEpochSecond’ is not a member of ‘org.eclipse.smarthome.core.library.types.DateTimeType’; line 32, column 24, length 51

2 Likes

You will need to use something like (riseStart.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000. I recently added this to the draft release notes…

2 Likes

Thanks @5iver, based on this, I was able to get this working using;

rule "Calculate time of day state"
when
    System started or
	Channel 'astro:sun:local:morningNight#event' triggered END or // Dawn 
    Channel 'astro:sun:local:civilDawn#event' triggered START or  // Morning
	Channel 'astro:sun:local:rise#event' triggered END or // Day
    Channel 'astro:sun:local:civilDusk#event' triggered START or // Twilight
	Channel 'astro:sun:local:civilDusk#event' triggered END or // Evening
	Channel 'astro:sun:local:morningNight#event' triggered START or // Night
	Time cron "0 0 0 * * ? *"
then
  Thread::sleep(1000) // make sure we are a tad past midnight to give Astro a chance to recalculate DateTimes for today

  val long dawn = (DawnStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000
  val long morning = (MorningStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000
  val long day = (DayStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000
  val long twilight = (TwilightStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000
  val long evening = (EveningStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000
  val long night = (NightStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000

  var curr = "UNKNOWN"

  switch now {
        case now.isAfter(dawn) && now.isBefore(morning):		curr = "Dawn"
        case now.isAfter(morning) && now.isBefore(day):     	curr = "Morning"
        case now.isAfter(day) && now.isBefore(twilight):		curr = "Day"
        case now.isAfter(twilight) && now.isBefore(evening):	curr = "Twilight"
        case now.isAfter(evening) && now.isBefore(night):		curr = "Evening"		
        case now.isAfter(night):								curr = "Night"
  }

  if(TimePeriodOfDay.state.toString != curr) {
    logInfo("EXTRA", "Current time of day is now " + curr)
	sendMail("email@ddre.ss", "Time of Day", "It's " + curr)							
    TimePeriodOfDay.sendCommand(curr)
  }
end```
 
and


```php

rule "Dawn Started"
when
	Item Dawn changed to ON or
	Channel 'astro:sun:local:morningNight#event' triggered END or //MorningNight end, signals start of Dawn
	Item TimePeriodOfDay changed to Dawn
then
        logInfo("EXTRA", "Its Dawn: " + now)
		logInfo("EXTRA", "Channel astro:sun:local:morningNight#event triggered END")		
		sendMail("email@ddre.ss", "Time of Day", "Its Dawn: " + now)				
        Dawn.sendCommand(ON)
		Morning.sendCommand(OFF)			
        Day.sendCommand(OFF)
		Twilight.sendCommand(OFF)			
        Evening.sendCommand(OFF)
        Night.sendCommand(OFF)
        TimePeriodOfDay.postUpdate("Dawn")
end

rule "Morning Started"
when
	Item Morning changed to ON or
	Channel 'astro:sun:local:civilDawn#event' triggered START or //Morning, after night, triggered by the start of civilDawn
	Item TimePeriodOfDay changed to Morning
then
		logInfo("EXTRA", "Its Morning: " + now)
		logInfo("EXTRA", "Channel astro:sun:local:civilDawn#event triggered START")		
		sendMail("email@ddre.ss", "Time of Day", "Its Morning: " + now)				
		Dawn.sendCommand(OFF)
		Morning.sendCommand(ON)
		Day.sendCommand(OFF)
		Twilight.sendCommand(OFF)
		Evening.sendCommand(OFF)
		Night.sendCommand(OFF)	
		TimePeriodOfDay.postUpdate("Morning")
end

rule "Day Started"
when
	Item Day changed to ON or
	Channel 'astro:sun:local:rise#event' triggered END or //Sunrise
	Item TimePeriodOfDay changed to Day
then
        logInfo("EXTRA", "Its Day: " + now)
		logInfo("EXTRA", "Channel astro:sun:local:rise#event triggered END")
		sendMail("email@ddre.ss", "Time of Day", "Its Day: " + now)						
        Dawn.sendCommand(OFF)
		Morning.sendCommand(OFF)
        Day.sendCommand(ON)
		Twilight.sendCommand(OFF)			
        Evening.sendCommand(OFF)
        Night.sendCommand(OFF)
        TimePeriodOfDay.postUpdate("Day")
end

rule "Twilight Started"
when
	Item Twilight changed to ON or
	Channel 'astro:sun:local:civilDusk#event' triggered START or //civilDusk with -120 offset, starts to get dark from here
	Item TimePeriodOfDay changed to Twilight	
then
		logInfo("EXTRA", "Its Twilight: " + now)
		logInfo("EXTRA", "Channel astro:sun:local:civilDusk#event triggered START")
		sendMail("email@ddre.ss", "Time of Day", "Its Twilight: " + now)				
		Dawn.sendCommand(OFF)
		Morning.sendCommand(OFF)
		Day.sendCommand(OFF)
		Twilight.sendCommand(ON)
		Evening.sendCommand(OFF)
		Night.sendCommand(OFF)	
		TimePeriodOfDay.postUpdate("Twilight")	
end

rule "Evening started"
when
	Item Evening changed to ON or
	Channel 'astro:sun:local:civilDusk#event' triggered END or //Evening, triggered by civilDusk End
	Item TimePeriodOfDay changed to Evening	
then
        logInfo("EXTRA", "Its Evening: " + now)
		logInfo("EXTRA", "Channel astro:sun:local:set#event triggered START")
		sendMail("email@ddre.ss", "Time of Day", "Its Evening: " + now)				
        Dawn.sendCommand(OFF)
		Morning.sendCommand(OFF)
        Day.sendCommand(OFF)
		Twilight.sendCommand(OFF)		
        Evening.sendCommand(ON)
        Night.sendCommand(OFF)
        TimePeriodOfDay.postUpdate("Evening")
end

rule "Night started"
when
	Item Night changed to ON or
	Channel 'astro:sun:local:morningNight#event' triggered START or //Night, an hour or so before midnight
	Item TimePeriodOfDay changed to Night	
then
        logInfo("EXTRA", "Its Night: " + now)
		logInfo("EXTRA", "Channel astro:sun:local:morningNight#event triggered START")
		sendMail("email@ddre.ss", "Time of Day", "Its Night: " + now)				
		Dawn.sendCommand(OFF)
		Morning.sendCommand(OFF)
        Day.sendCommand(OFF)
		Twilight.sendCommand(OFF)			
        Evening.sendCommand(OFF)
        Night.sendCommand(ON)
        TimePeriodOfDay.postUpdate("Night")
end```
1 Like

You should remove the

* 1000

from the example in the release notes, this was only in Vini´s rule.

I don’t understand what you mean. The * 1000 is needed to convert to milliseconds.

hm, i thought, this was only in this special rule…

I have changed all my rules to the new way without * 1000 and i didn´t see any problems so far.

So the right update of the rule is this?

old:
val dawn = new Date((DawnStart_Time.state as DateTimeType).calendar.timeInMillis)

new:
val dawn = new Date((DawnStart_Time.state as DateTimeType).getZonedDateTime.toEpochSecond * 1000)

What do i get when i don´t use * 1000 ? Is the new thing not in milliseconds? Is this 1/1000 milliseconds?

This is my rule and it works without *1000:

rule "Xiaomi Temp 4 time since"
when
		Time cron "0 * * * * ?"
then
		var Number lastthingy4 = (Xiaomi_Temp_4_last_connection.state as DateTimeType).getZonedDateTime.toEpochSecond
		var Number myminutes4 = ((now.millis - lastthingy4) / 60000)
		Xiaomi_Temp_4_time_since.postUpdate(myminutes4)
end

I get the same results as before with “.calendar.timeInMillis”.

Why???

EDIT:

Strange, now i see it, now after some hours of running the updated rule i see the wrong values.

You are right, i need * 1000 in this rules too.

The .toEpochSecond method returns a Long, which represents the number of seconds since 1970-01-01T00:00:00Z.

https://docs.oracle.com/javase/8/docs/api/java/time/chrono/ChronoLocalDateTime.html#toEpochSecond-java.time.ZoneOffset-

And the old one? Which number did i get with it?

seconds since 1970 too?

The old one (.calendar.timeInMillis) returned milliseconds since the start of the Unix Epoch.

More accurate version was just posted here…