Time zone of a datetime attribute changing

I’m using a rest sensor to pull some electricity pricing, including datetimes to which the future pricing applies.
However, while the rest sensor returns the correct datetime string
eg tradingDateTime: 2022-08-01T11:30:00+12:00 for my timezone.
The sensors that are created by that attribute being filtered by a template sensor are not correct, eg 2022-07-31T23:30:00+00:00. I don’t do any manipulation of that value/string (that I know of).

the “+12 hours ahead” is removed - some how it is converted to UTC.

To re-phrase:
The rest payload shows the correct datetime. When the datetime attribute is filtered to a sensor, something changes the time zone!

should I not have the device class defined as “timestamp”?
From the Sensor - Device Class page I used this as my reason to define the class:

  • timestamp: Datetime object or timestamp string (ISO 8601)

my yaml:

rest:
  - authentication: basic
    method: GET
    headers:
      Authorization: Bearer {{ states('sensor.token') }}
      Accept: application/json
    scan_interval: 180
    resource: 'https://etc....'
    sensor:
      - name: "forecast_price"
        json_attributes_path: "$.[0].prices[0]"
        value_template: "OK"
        json_attributes:
          - "schedule"
          - "tradingDateTime"
          - "tradingPeriod"
          - "node"
          - "price"
          - "lastRunTime"

The template sensor that filters rest attributes to sensors - for example:

template:
  - sensors:
      trading_date_time:
        value_template: "{{ state_attr('sensor.price_forecast', 'tradingDateTime') }}"
        device_class: timestamp

EDIT: just to be clear, my HA time zone is set to GMT+13

Maybe try as_local().

Also do you realise that as you are using the rest integration, you can have as many sensors as you want from the one call to the resource?

Or do you want to use attributes and templates sensors for some reason?

e.g.

rest:
  - authentication: basic
    method: GET
    headers:
      Authorization: Bearer {{ states('sensor.token') }}
      Accept: application/json
    scan_interval: 180
    resource: 'https://etc....'
    sensor:
      - name: "Forecast Price"
        json_attributes_path: "$.[0].prices[0]"
        value_template: "{{ json_value[0].prices[0].price }}"
        unit_of_measurement: "$"

      - name: "Trading Date"
        json_attributes_path: "$.[0].prices[0]"
        value_template: "{{ as_local(json_value[0].prices[0].tradingDateTime) }}"

      - name: "Schedule"
        json_attributes_path: "$.[0].prices[0]"
        value_template: "{{ json_value[0].prices[0].schedule }}"
        json_attributes:
          - "tradingPeriod"
          - "node"
          - "lastRunTime"

You can convert your datetime string to a datetime object using as_datetime('DatetimeStringHere') then convert to local time using astimezone():

{{ as_datetime('2022-07-31T23:30:00+00:00').astimezone() }}

That should convert the UTC time to your local zone. For me in PDT I get 2022-07-31 16:30:00-07:00 Hope this helps!

3 Likes