As_datetime template failing after update

I have a Template using as_datetime that is now failing after an update. I can’t actually find the docs for this function.

{{(states('sensor.octopus_2hour_time')| as_datetime) < now()}}

The sensor;


It was working (tested in Developer Tools).

The error now:



This in the Template area of Developer tools returns unknown


I created this from an old thing called OctoBlock for AppDaemon - has something changed?

Guessing the device_type needs to be there :face_with_symbols_over_mouth: :face_with_symbols_over_mouth: :face_with_symbols_over_mouth:. Bugger.

Surely the Template should just take the string as just that, a string? It teats most integers/floats as strings.

The as_datetime() should take a properly formatted datetime string without issues. But, if your sensor goes offline or is unavailable at reload/restart, the template isn’t receiving a datetime string and you end up with the error. If this is for a Template sensor you should include an availability template to avoid such errors.

Ok, thanks.

The string is an ISO format so therefore it should accept it with out the device_class being set?

If so, it seems it isn’t, Where would be the correct place to raise this as an issue?

I have a feeling this is an obscure feature of Python that I can across before…

The to_isoformat function never produces a date time string with a Z in it.

The from_isoformat is the inverse of the to_isoformat function so it will not covert an ISO string with a Z in it.

Issue 35829: datetime: parse "Z" timezone suffix in fromisoformat() - Python tracker.

Is Home Assistant attemnpting to do a conversion in the background first and failing? If it was returned as a string, then you could process that to delete the Z before using as_datetime.

The as_datetime function will parse datetime strings with either Z or an “HH:MM” offset.


The failure in the template is due to the state of the sensor being unknown.


You need to figure out why your OctoBlock sensor isn’t working reliably.

If this template is being used in a Template sensor you likely will want to configure an availability to avoid getting the error during restart/reload when the state of the Octoblock sensor is unavailable.

1 Like

Why then in the ‘States’ view in Developer tools, does it show a value?

Very odd.

I’ve wasted too much time on this so using another method to calculate the block.


From the top.

as_datetime() is a Home Assistant specially added function in templates and the documentation can be found here

The underlying code for Jinja templating is Python, and therefore uses the date time library.
An alternative function would be strptime(), with the difference that this permits a default value.

date times as strings are ISO formatted if the date is separated from the time by ‘T’.

In many languages, datetime strings with timezone identifiers are processed precisely to the given zone, whereas without a timezone they are treated as local time.
The ‘Z’ is for Zulu time, being GMT and UTC. As such there is no ambiguity and the datetime string as provided will be converted correctly to the datetime object. Octopus Energy always generate rates using UTC.

Octoblock generates sensor entities in HA based on the Agile prices just read in, and your definition yaml of what you are looking for. The 2 hour sensor will hold the start datetime of a period where the incoming prices are lowest for two hours.

This, I read, works either on an all-day basis, or just from ‘now’, and clearly if the API call has failed, and you have opted for the from now setting, and there are less than 2 hours of data between now and 22:30, the octoblock code will return the Python ‘none’ for the lowest 2 hour price block.

The error message is very clear. HA is seeing a sensor with state value ‘none’.

When you test a template in the developer sandbox, it will update on edit, regularly, and on state changes. Hence {{states(‘sens. }} will be unavailable (HA speak) for state’ none’ and will reflect the latest state value.

The developer > states page is not updated, and together with the Web page cache, means that the state shown was the last one seen when the page was generated. If you want the “now” state, you need to refresh the page, or click on the entity link to load the state into the state editing box at the top.

So, in conclusion, you were looking at your octoblock 2hour sensor just before 21:00,with the last 2 hour block of the day being 21:00 to 23:00. Octopus rates have not been updated (due to whatever), and just after 21:00 the octoblock half-hourly update can no longer find 2hours left in the day, so updates the sensor with the Python None, and the rest is history.

Root cause: Octopus rate API call not completed successfully before 2 hours prior to end of rate table.

Solution: debug that failure and/or modify original template to cope with unavailable states, on the rare occasion it happens

Education: if you want the latest sensor value in Developer > States page, refresh the page

I rest my case m’lud.


You’re most likely getting issues on startup when the sensor isn’t populated with a valid date for as_datetime


Good, but this must be done outside of just using the standard Python functions.

Yes, it is old code, not maintained so time to retire it.

Ok, thanks - I’ll remember that. I’m reasonably sure it was a fresh impression, but possible the cache caused an issue :frowning:

Yes, thanks - not something I had appreciated and thanks for the reply :slight_smile:

Well, what he said is not true. Developer tools → states page live updates.

Anyways, back to the topic at hand, you were getting the error on startup. @Didgeridrew showed that your template is valid as long as the sensor has a value. I.e. the real solution in the thread is to add a availability template to your original template sensor to remove the error.

Maybe - it is too long ago now to be sure, but as the image I posted showed, It was there as a state in the developer tools page, switching to the template in another tab and returned unknown.

Never quite got a handle on using these :frowning: