Problem with timestamps using now() and utcnow(), and adjusting sensors to Daylight Saving Time (DST)

Hello,

After hours of reading documentation, forums and tinkering with templates I cannot solve what seems a very basic problem so I need some help.

My energy company has a tariff where the price of electricity changes every 30mins. This information is available in the form of a REST API which looks like this:
Screenshot 2024-05-02 004702

I have the following sensor set up which worked like a charm - until Daylight Saving Time (DST) kicked in a little while ago.

- platform: rest
  name: electricity_cost
  resource_template: >-
    https://api.octopus.energy/v1/products/AGILE-23-12-06/electricity-tariffs/E-1R-AGILE-23-12-06-G/standard-unit-rates/?period_from=
    {% set ts_now = ((as_timestamp(now())/1800)|round(0,'floor')|int * 1800) %}
    {{ ts_now |timestamp_custom ('%Y-%m-%dT%H:%M:%SZ') }}&period_to=
    {{ (ts_now + 1800) |timestamp_custom ('%Y-%m-%dT%H:%M:%SZ') }}
  value_template: "{{ (value_json.results[0].value_inc_vat) | round(2) }}"
  unit_of_measurement: "p/kWh"

The problem is that the REST API provides all values in UTC time. When DST kicked in I simply added -3600 to the calculations and all is well however I was looking for a solution that would work across DST changes without having to modify it manually.

During my research I discovered that templating has several options for current time: now() which displays current time in local timezone as well as utcnow() which displays time in UTC timezones. Now I live in UK which is same as UTC half of the year and then it is at UTC+1 for the other half (right now during DST). For some reason, however, templating both now() and utcnow() gives me the exact same time - i.e. my local time.

Time zone in HA is set correctly to GMT +0 London. I’ve been banging my head against the wall. I’ll admit that working with timezones can get confusing but I’ve checked my work, my settings and documentation Templates, dates and times - Home Assistant several times but cannot find any mistakes.

Questions:

  1. Why is now() and utcnow() returning the same (local) time for me?
  2. If for any reason I won’t be able to use utcnow() for my sensor, what other options are there?

Thanks for any input.

The template you used above will give the same result for both now() and utcnow() as input, because you convert it to a timestamp with as_timestamp

a timestamp is always the number of seconds past midnight UTC of 1st of January 1970. So as_timestamp(now()) and as_timestamp(utcnow()) will give the same result.

Your problem is that after that, you use timestamp_custom which by default uses the local time. You should add the parameter false to it so it uses UTC.

This should resolve your issues:

- platform: rest
  name: electricity_cost
  resource_template: >-
    https://api.octopus.energy/v1/products/AGILE-23-12-06/electricity-tariffs/E-1R-AGILE-23-12-06-G/standard-unit-rates/?period_from=
    {% set ts_now = as_timestamp(now()) // 1800 * 1800 %}
    {{ ts_now | timestamp_custom ('%Y-%m-%dT%H:%M:%SZ', false) }}&period_to=
    {{ (ts_now+1800) | timestamp_custom ('%Y-%m-%dT%H:%M:%SZ', false) }}
  value_template: "{{ (value_json.results[0].value_inc_vat) | round(2) }}"
  unit_of_measurement: "p/kWh"

alternative approach without conversion to timestamps

- platform: rest
  name: electricity_cost
  resource_template: >-
    https://api.octopus.energy/v1/products/AGILE-23-12-06/electricity-tariffs/E-1R-AGILE-23-12-06-G/standard-unit-rates/?period_from=
    {{- utcnow().replace(minute=now().minute // 30 * 30).strftime('%Y-%m-%dT%H:%M:%SZ') -}}&period_to=
    {{- (utcnow().replace(minute=now().minute // 30 * 30 + 30)).strftime('%Y-%m-%dT%H:%M:%SZ') -}} 
  value_template: "{{ (value_json.results[0].value_inc_vat) | round(2) }}"
  unit_of_measurement: "p/kWh"
1 Like

Thank you!

Took me a little while but now I understand why now() and utcnow() would result in the same timestamp.

Used your suggestions and it works accurately now. Many thanks!