No, that change was made a long time ago, simply remove the .isoformat(). That’s updated what I linked
it still outputs: 2023-10-29 03:00:00+01:00
without the T there, so (a mMac) wont display that correctly when used as timestamp?
the beauty of the earlier template is that it calculates 2 dates, for spring and fall change. Id love to keep those really
No? Timestamp sensors in home assistant require a datetime object being the output. They all output without the T. The T is part of ISOs format.
ok let me test that, I had difficulties with those before, especially on Mac, but maybe that hs changed.
I’m not sure how you could have had ‘difficulty’ with them when HA does all the work. Also, keep in mind that all timestamp sensors are like this, i.e. ones that come from integrations that you have no control over.
EDIT: And once you create the sensor, you’ll see the T is in the state too. HA does this beyond the template.
it said ‘Invalid format’ in the frontend.
there are still some idiosyncrasies there, check this
entity in an entities card, without anything further:
clicking that reveals:
note the actual date in the state, and the datetime s in the attributes
3 different formats for a single template syntax…
The old template is wrong and does not work. You can’t trust it. The new template works. As for the entities card, that’s what HA does with timestamps, that has nothing to do with the template itself.
the template is correct…
Keep in mind that 2am is 3am when DST is not applied. So the timestamp is correct it just doesn’t say ‘3am’, however the number of days, hours, and minutes from now to dst is correct.
btw, this is what I referred to: Templating - Home Assistant
the yellow warning above that:
If your template is returning a timestamp that should be displayed in the frontend (e.g., as a sensor entity with
device_class: timestamp
), you have to ensure that it is the ISO 8601 format (meaning it has the “T” separator between the date and time portion). Otherwise, frontend rendering on macOS and iOS devices will show an error. The following value template would result in such an error:
{{ states.sun.sun.last_changed }}
=>2021-01-24 07:06:59+00:00
(missing “T” separator)To fix it, enforce the ISO conversion via
isoformat()
:
{{ states.sun.sun.last_changed.isoformat() }}
=>2021-01-24T07:06:59+00:00
(contains “T” separator)
Yes, but you’re not understanding what HA does under the hood.
device_class:timestamps REQUIRE a datetime object being returned. Not a string. This is a requirement. So using isoformat() will result in an error in the logs. After the template is resolved, HA will take the datetime object and format it in isoformat. Just look at the state of the sensor in developer tools instead of arguing. You’ll see that the state has a T in it. The template in the template editor will not have the T because it hasn’t been resolved by the template sensor code.
yes, that is correct, (for the state, not the attributes though)
not arguing here, simply trying to understand why things are not equal throughout the system.
given the state used here is
{{([ns.spring,ns.fall]|min)}}
and the attributes are:
{%- set next = [ns.spring, ns.fall] | reject('<',now())|min %}
{"spring": "{{ns.spring}}",
"fall": "{{ns.fall}}",
etc etc
wouldn’t it be expected these attributes also show the T?
well, it was a bit quirky with the range set too tight, now it does work correctly
No because you aren’t using isoformat. You’re just outputting the datetime as a string. Remember device_class: timestamp
has extra steps to turn datetimes into iso formatted datetime strings. Attributes do not, so you have to do it.
It does not work, it will be off by an hour. There is no way to get the correct time of the second transition due to the nature of DST. It will always be off by 1 hour.
EDIT: Well there probably is a way but it would be a ton of work for no gain. You’d have figure out your next loss/gain and inverse that value on the following loss/gain.
hehe, I had those, but just took them out because of your suggestion…will reset that.
o that is what you meant. Yes, that I can confirm…
in good company though as even Brittanica is an hour off for Europe…
Getting back to my earlier search:
how to find the 2 next DST changes (which will always be on last Sunday in March and October, which ever comes first), and yes, ofc preferably with the correct timing.
Summertime 02 → 03 am, Wintertime 03 → 02 am. Since those are fixed they needn’t even be templated?
yeah, I guess it’s not really that important for the second change. In fact it would only need to be a date.
I would merely like to have the sensor update after the actual first change, so it does not display the full Sunday ’ today there’s a DST change’.
technicaly it would be correct of course, but at 3 am, it would preferably change to show the next two changes
The first would therefor need to be correct to the hour.
They aren’t fixed.
sure, not globally. but they are in EU… and I was after that
After struggling with “the last x of the month” for a while I now use this method……
Find the first x of the following month and subtract 7 days. Very reliable.
That’s typically how you’d do it in code anyways. Time is a PITA
My (very belated) attempt at the original question:
There’s a subtlety lurking there in the word “next” — if it’s already past the last Wednesday of this month, it should show next month’s last Wednesday. My solution below as a single-line (split for readability) template, not using loops, namespaces or if
statements, but after a lot of iterations and an unhealthy obsession on this particular puzzle. The 2
in the top line is the weekday number for Wednesday.
{{ ((range((now().replace(hour=12)-timedelta(days=now().weekday()-2))|as_timestamp|int,
(now()+timedelta(days=80))|as_timestamp|int,
604800)
|select('>',now().replace(hour=11)|as_timestamp())
|map('as_datetime')
|groupby('year')
|first)[1]
|groupby('month')
|first)[1][-1].date() }}
- Creates a list of timestamps spaced a week (604,800s) apart out for 80 days (a safe number to consider all of this month and next) starting from midday on a Wednesday: might be the previous one or the next one depending where we are in the current week;
- Filters out those days that are in the past;
- Transforms the remaining days into
datetime
objects; - Groups them by year and takes the list of dates in the earliest year (if there is more than one; a prior attempt missed this nuance and failed to calculate across year boundaries correctly);
- Groups by month and takes the first month with a Wednesday in it;
- Gets the last item in that list and converts it to a date.
When in doubt, run your code in the Developer Tools → Template tool, you’ll see the problem. When I paste your value template in there here’s the output:
TypeError: 'weekday' is an invalid keyword argument for replace()