Return Weather Hourly Forecast for LOCAL Timezone Current Day

I’ve started playing around with creating some sensors via weather.get_forecasts, but I’m observing an issue regarding how time is returned within PirateWeather. I’ve parsed some info via templates and their outputs below to better outline my issue.

(the sensor.forecast_hottest_time is an idea I got from here. Filters the returned list to match today’s date, sorts them in descending order by temp, then returns the first entry)

PirateWeather Time: {{ states('sensor.forecast_hottest_time') }}

PirateWeather TimeStamp: {{ as_timestamp(states('sensor.forecast_hottest_time')) 
                             | timestamp_custom('%I:%M %p') }}

Now:  {{ now() }}

Now TimeStamp: {{ as_timestamp(now()) 
                   | timestamp_custom('%I:%M %p') }}

PirateWeather Time: 2025-02-28T23:00:00+00:00
PirateWeather TimeStamp: 06:00 PM
Now: 2025-02-28 10:37:00.223762-05:00
Now TimeStamp: 10:37 AM

As you can see, my timzone is UTC -5. I have PirateWeather pulling data according to my Home Lat and Long. However, my issue is as follows:

  • you can see the returned local time of 23:00:00+0 is 6 pm for me
  • in PirateWeather hourly forecast, after 2025-02-28T23:00:00+00:00, it obviously changes over to the next day at 2025-03-01T00:00:00+00:00
  • with the following information, it’s technically only returning the hottest temp for the day up to 6 pm local time.

Confirming my observation via Actions in Developer Tools, all times are being returned via PirateWeather forecast is UTC+0:00

Any input or fix for my issue is greatly appreciated!

EDIT: this problem exists with other weather entities as well, not just PirateWeather

Are you using the same methodology as the linked post, i.e. pulling the data at midnight?

Yes, but also on homeassistant restart to make sure I can test them after a restart :wink:. The sensors are working correctly as that time is technically the forecasted warmest in the day (its warming up into the next day)…

EDIT: well I guess the warmest in the UTC+0 day (this is my issue)

Apologies, I see I’ve technically fallen victim to the XY Problem.

I guess my real issue is all the datetime returned by PirateWeather is UTC+0 despite my latitude and longitude in configuration.

Via developer tools:

action: weather.get_forecasts
target:
  entity_id: weather.pirateweather
data:
  type: hourly

all datetimes are returned as UTC+0 (in fact, performing the action it right now (11:05 AM local time) the first entry is as follows:

- datetime: "2025-02-28T15:00:00+00:00"

I’m guessing I can’t simply match based on the day, but have to convert all datetimes output by PirateWeather to local time first, before running a date match filter.

Just curious if other PirateWeather users have experience with this

An easier approach to get just the current day’s value is index slicing:

{% set remaning_hours = 25 - now().hour%}
{{ (hourly['weather.pirateweather'].forecast[:remaning_hours]
| sort(attribute='temperature' , reverse=true))[0]['datetime'] }}

The issue with triggering at times other than midnight is that the forecasts that are provide will only contain values from the current hour onward. If your query happens after the hottest hour, the value returned will not be the hottest hour of the day.

1 Like

This is a genius fix. Thank you!

I guess I’m just bummed there’s no fix to return local timezone datetimes within weather.get_forecasts. It’s weird…

I understand the issue you mentioned regarding the code, so if I return it to only trigger at midnight, that is

- trigger:
    - trigger: time_pattern
      # this will update every night at midnight
      hours: 0
      minutes: 0

then 25 - 0 = 25. Then the list return forecast[:remaning_hours]will be from range [0:25]? This would return the next 25 entries (hours) no?

Should it be

{% set remaning_hours = 24 - now().hour%}

Thanks again.

I would just use a standard Time trigger instead of a Time pattern trigger, but either will work.

Yes, my mistake. Though, it shouldn’t matter since weather integrations usually only return 24 hourly items. If you are only triggering at midnight, and Pirate weather doesn’t return more than 24 items, you don’t need to use slicing at all.

All datetimes in HA are UTC, so that all the cards, triggers, etc have a standard frame to work from. If you don’t plan on using the sensor for those kind of uses, you can remove the device_class: timestamp from the sensor configuration so the state is WYSIWYG:

template:
  - trigger:
      - trigger: time
        at: "00:00:00"
    sensor:
      - name: Pirate Weather Hottest Hour
        state: | 
          {{ ((hourly['weather.pirateweather'].forecast
          | sort(attribute='temperature' , reverse=true))[0]['datetime'] 
          | as_datetime | as_local).strftime('%-I:%M %p') }}
1 Like

Ah right, good call.

Fantastic logical thought. Actually, I just checked and PirateWeather returns hourly entries for the next 7 days! lol (didn’t expect that). Either way, will run your range list fix. Thank you.

This makes sense. Working with time in HA is relatively new for me (just started HA journey in January), and I gotta be honest all the time coding and formats gets me spun around sometimes.

Its cool to see {{ as_timestamp("2025-03-01T04:00:00+00:00") | timestamp_custom('%I:%M %p')}} actually returns as 11pm of Feb 28, for me.

A thought I had as well, but figured I would keep as timestamp in case down the line I want to trigger things based on this information. To return it more readable in an entity card (I usually use Mushroom Template cards), I’ll template within that to return a more readable time format.

Thank you for your help @Didgeridrew :beers: