State: {{ states('sensor.steves_phone_next_alarm') }}
Attribute: {{ state_attr('sensor.steves_phone_next_alarm', 'Time in Milliseconds') / 1000 }}
State as Timestamp: {{ (as_timestamp(states('sensor.steves_phone_next_alarm'))) }}
returning
State: 2020-11-04T15:25:00.000Z
Attribute: 1604503470.0
State as Timestamp: 1604503500.0
Looking at the code, I wonder if it is because the next alarm time returned by the AlarmManager is a Long but the SensorManager is treating the “Time in Milliseconds” attribute as a float (Long and Float are both subclasses of Number):
This could be resulting in floating point conversion issues.
I’ve confirmed that the floating point conversion is likely to be the cause of the issue by running this code in an online Kotlin compiler:
fun main() {
val originalTimeStamp: Long = 1234567890;
val timeStampString = originalTimeStamp.toString();
val timeStampFloat = timeStampString.toFloat();
val timeStampLong = timeStampString.toLong();
System.out.format("Original %d\n", originalTimeStamp);
System.out.format("String %s\n", timeStampString);
System.out.format("Float %f\n", timeStampFloat);
System.out.format("Long %d\n", timeStampLong);
}
and getting this response
Original 1234567890
String 1234567890
Float 1234567936.000000
Long 1234567890
So, the alarm timestamp is being converted from a Long into a string (to store it in the app database) and then back into a Float which is causing the value to change. If it is converted from the string into a Long, the same issue doesn’t occur.
I’ve tested this fix in Android Studio with an emulated device, and the “Time in Milliseconds” attribute (when divided by 1000) exactly matches the timestamp from the state.