Sensor.sunrise and sensor.sunset in sync for today's date

Hi everyone. I want to get my sensor.sunrise and sensor.sunset to stay in sync with the date. The sunrise and sunset time is based in a longitude and longitude that I set in configuration.

Yesterday (6), the sunrise time is 7:01 and sunset time is 20:31.
Today (7) the sunrise time is 7:02 and sunset time is 20:30.
Tomorrow (8), the sunset time will be 20:29.

Right now in Home Assistant frontend, the sunrise time is 7:02 and sunset time is 20:29.

Couldn’t Home Assistant write the sunrise and sunset time to a MySQL database? Here’s my MySQL statement:

SELECT DISTINCT
       DATE_FORMAT(convert_tz(last_updated,"Etc/UTC",
                   "America/New_York"),"%Y-%m-%d") as date,
       convert_tz(last_updated,
                   "Etc/UTC","America/New_York") AS last_changed,
       state, entity_id
FROM states
WHERE entity_id = "sensor.sunrise" OR entity_id = "sensor.sunset"
GROUP BY state
ORDER BY date, entity_id;

A MySQL query outputs the following table:

+------------+---------------------+-------+----------------+
| date       | last_changed        | state | entity_id      |
+------------+---------------------+-------+----------------+
| 2018-08-05 | 2018-08-05 21:40:48 | 07:01 | sensor.sunrise |
| 2018-08-05 | 2018-08-05 21:40:48 | 20:31 | sensor.sunset  |
| 2018-08-06 | 2018-08-06 20:31:37 | 20:30 | sensor.sunset  |
| 2018-08-07 | 2018-08-07 07:02:00 | 07:02 | sensor.sunrise |
| 2018-08-07 | 2018-08-07 20:30:46 | 20:29 | sensor.sunset  |
+------------+---------------------+-------+----------------+

I’ve been thinking of this:

SELECT DISTINCT
       DATE_FORMAT(convert_tz(sunrise.last_changed,"Etc/UTC",
                   "America/New_York"),"%Y-%m-%d") as sunrise_date,
       sunrise.state, sunset.state
FROM states sunrise, states sunset
WHERE sunrise.entity_id = "sensor.sunrise" AND sunset.entity_id = "sensor.sunset"
GROUP BY sunrise.state;

…which produces:

+--------------+-------+-------+
| sunrise_date | state | state |
+--------------+-------+-------+
| 2018-08-05   | 07:01 | 20:31 |
| 2018-08-07   | 07:02 | 20:31 |
+--------------+-------+-------+

However, that’s innacurate.

I should probably start a thread over in the database forum, but based in the first two rows, I’ve been thinking:

Can I have Home Assistant update the sunrise and sunset time after midnight? The second MySQL query can work if I can update the last_updated and last_changed column for the sensor.sunrise and sensor.sunset.

This is the sensor.yaml configuration that I am using:

- platform: template
  sensors:
    solar_angle:
      value_template: '{{ states.sun.sun.attributes.elevation }}'
      friendly_name: 'Sun angle'
      unit_of_measurement: 'degrees'
    sunrise:
      value_template: '{{ as_timestamp(states.sun.sun.attributes.next_rising) | timestamp_custom("%H:%M") }}'
    sunset:
      value_template: '{{ as_timestamp(states.sun.sun.attributes.next_setting) | timestamp_custom("%H:%M") }}'

Sorry, didn’t thoroughly read your whole post, but if you’re looking for a version of the sun component that includes today’s sunrise and sunset values (and which are available throughout the entire day), I took the existing component and modified it to do just that. You can install it as a custom component (i.e., place a copy in <config>/custom_components/sun.py, where <config> is your HA config directory. You can get the code here:

https://github.com/pnbruckner/homeassistant-config/blob/master/custom_components/sun.py

1 Like

Further to what @pnbruckner said, you might find the discussion about this in this thread Hours of Daylight interesting.

1 Like

Thank you for the code @pnbruckner. If all goes well tomorrow and the next few days, I will mark your post as a solution.

I’m currently using MySQL statement in Grafana:

SELECT DISTINCT
       DATE_FORMAT(convert_tz(sunrise.last_changed,"Etc/UTC",
                   "America/New_York"),"%Y-%m-%d") as date,
       sunrise.state AS sunrise, sunset.state AS sunset
FROM states sunrise, states sunset
WHERE sunrise.entity_id = "sensor.sunrise" AND sunset.entity_id = "sensor.sunset";

I cleared out the old sunset and sunrise times to start anew and so far, I have a result:

+------------+---------+--------+
| date       | sunrise | sunset |
+------------+---------+--------+
| 2018-08-08 | 07:03   | 20:29  |
+------------+---------+--------+

I’ll be watching Grafana and see how will it turns out.

Thanks.

Okay. I have the sunrise and sunset times in my database table and I have what I wanted, so my final code is going to be in Grafana:

SELECT DISTINCT(DATE_FORMAT(convert_tz(sunrise.last_changed,"Etc/UTC","America/New_York"), "%Y-%m-%d")) as date,
       sunrise.state AS sunrise, sunset.state AS sunset
FROM states sunrise, states sunset
WHERE sunrise.entity_id = "sensor.sunrise" AND sunset.entity_id = "sensor.sunset"
  AND STR_TO_DATE(sunrise.last_changed,"%Y-%m-%d") = STR_TO_DATE(sunset.last_changed,"%Y-%m-%d")
GROUP BY date;

The reason for the “GROUP BY date” is every time Home Assistant restarts when I tell it to or once I perform updates to my Ubuntu Server, Home Assistant writes the sensor.sunrise and sensor.sunset times to the state field, which causes the duplicate.

Anyway, it’s working.

Thanks.

Hello, I’m new to HA. I am improving the automation of my home and I confess to having difficulty with the ‘sun.sun’ sensor since it maintains the ‘next_ *’ attribute and does not refer to the current day. This matters to me because I want to know the times when the automations calculated from the attributes of ‘sun.sun’ will be performed. I read several posts in the community, including some solutions using inputs along with automation or even customized component ‘sun.sun’. I am sharing the code I developed that requires only the definition of sensors. This set of sensors reflects the time or time interval of the ‘sun.sun’ sensor.

Initially (just after HA start / restart) the time of the sensors’%H:%M:%S’ reflects the values of the attributes ‘next_*’ of ‘sun.sun’, but containing the date of the current day ‘%Y-%m-%d’. After 24h the sensors start to effectively reflect the values of ‘sun.sun’ for the current day.

sensor:
#---------------------------------------------------
# Date
#---------------------------------------------------
  - platform: time_date
    display_options:
      - 'date_time_iso'
#---------------------------------------------------
# Sun
#---------------------------------------------------
# This set of sensors reflects the time of the 'next_ *'
# attributes of the 'sun.sun' sensor
  - platform: template
    sensors:
      sun_up:
        friendly_name: "Sun is up"
        entity_id: sun.sun
        value_template: >-
          {{ state_attr('sun.sun', 'elevation')|float > 0 }}

      sun_down:
        friendly_name: "Sun is down"
        entity_id: sun.sun
        value_template: >-
          {{ state_attr('sun.sun', 'elevation')|float < 0 }}

      sun_rising:
        friendly_name: 'Sun is rising'
        entity_id: sun.sun
        value_template: >
          {{ state_attr('sun.sun','rising') }}

      sun_elevation:
        friendly_name: "Sun Elevation"
        unit_of_measurement: 'degrees'
        entity_id: sun.sun
        value_template: >
          {{ state_attr('sun.sun', 'elevation') | float }}

      sun_azimuth:
        friendly_name: "Sun Azimuth"
        unit_of_measurement: 'degrees'
        entity_id: sun.sun
        value_template: >
          {{ state_attr('sun.sun', 'azimuth') | float }}

      sun_nextsundawn:
        device_class: timestamp
        friendly_name: 'Next Dawn'
        entity_id: sun.sun
        value_template: >
          {{ as_timestamp(state_attr('sun.sun','next_dawn')) | timestamp_local }}

      sun_nextsunrise:
        device_class: timestamp
        friendly_name: 'Next Sunrise'
        entity_id: sun.sun
        value_template: >
          {{ as_timestamp(state_attr('sun.sun','next_rising')) | timestamp_local }}

      sun_nextnoon:
        device_class: timestamp
        friendly_name: 'Next Noon'
        entity_id: sun.sun
        value_template: >
          {{ as_timestamp(state_attr('sun.sun','next_noon')) | timestamp_local }}

      sun_nextsunset:
        device_class: timestamp
        friendly_name: 'Next Sunset'
        entity_id: sun.sun
        value_template: >
          {{ as_timestamp(state_attr('sun.sun','next_setting')) | timestamp_local }}

      sun_nextdusk:
        device_class: timestamp
        friendly_name: 'Next Dusk'
        entity_id: sun.sun
        value_template: >
          {{ as_timestamp(state_attr('sun.sun','next_dusk')) | timestamp_local }}

      sun_nextmidnight:
        device_class: timestamp
        friendly_name: 'Next Midnight'
        entity_id: sun.sun
        value_template: >
          {{ as_timestamp(state_attr('sun.sun','next_midnight')) | timestamp_local }}
#---------------------------------------------------
# Sun Today
#---------------------------------------------------
# This set of sensors reflects the time or time interval of the 'sun.sun' sensor.
# Initially (just after HA start / restart) the time of the sensors'%H:%M:%S'
# reflects the values of the attributes 'next_*' of 'sun.sun', but containing
# the date of the current day '%Y-%m-%d'. After 24h the sensors start to
# effectively reflect the values of 'sun.sun' for the current day.

  - platform: template
    sensors:
      sun_dawn:
        device_class: timestamp
        friendly_name: 'Today Dawn'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_dawn'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_dawn'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_dawn')) | timestamp_local }}
          {% endif %}

      sun_sunrise:
        friendly_name: 'Today Sunrise'
        device_class: timestamp
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_sunrise'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_rising'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_sunrise')) | timestamp_local }}
          {% endif %}

      sun_midmorning:
        friendly_name: 'Today Midmorning'
        device_class: timestamp
        entity_id:
          - sensor.sun_sunrise
          - sensor.sun_noon
        value_template: >
            {% set tr = as_timestamp(states('sensor.sun_sunrise')) %}
            {% set tn = as_timestamp(states('sensor.sun_noon')) %}
            {{ ((tr + tn) / 2) | timestamp_local }}

      sun_noon:
        device_class: timestamp
        friendly_name: 'Today Noon'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_noon'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_noon'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_noon')) | timestamp_local }}
          {% endif %}

      sun_midafternoon:
        device_class: timestamp
        friendly_name: 'Today Midafternoon'
        entity_id:
          - sensor.sun_noon
          - sensor.sun_sunset
        value_template: >
            {% set ts = as_timestamp(states('sensor.sun_sunset')) %}
            {% set tn = as_timestamp(states('sensor.sun_noon')) %}
            {{ ((ts + tn) / 2) | timestamp_local }}

      sun_sunset:
        device_class: timestamp
        friendly_name: 'Today Sunset'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_sunset'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_setting'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_sunset')) | timestamp_local }}
          {% endif %}

      sun_dusk:
        device_class: timestamp
        friendly_name: 'Today Dusk'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_dusk'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_dusk'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_dusk')) | timestamp_local }}
          {% endif %}

      sun_midnight:
        device_class: timestamp
        friendly_name: 'Today Midnight'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_midnight'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_midnight'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_midnight')) | timestamp_local }}
          {% endif %}

      sun_dawntime:
        device_class: timestamp
        friendly_name: 'Today dawntime'
        entity_id:
          - sensor.sun_dawn
          - sensor.sun_sunrise
        value_template: >
            {% set td = as_timestamp(states('sensor.sun_dawn')) %}
            {% set tr = as_timestamp(states('sensor.sun_sunrise')) %}
            {% set midnight = as_timestamp(states('sensor.sun_sunrise'))
               | timestamp_custom("%Y-%m-%d 00:00:00", true) %}
            {% set midnight_ts = as_timestamp(midnight) %}
            {{ (midnight_ts + (tr - td)) | timestamp_local }}

      sun_daytime:
        device_class: timestamp
        friendly_name: 'Today daytime'
        entity_id:
          - sensor.sun_sunrise
          - sensor.sun_sunset
        value_template: >
            {% set tr = as_timestamp(states('sensor.sun_sunrise')) %}
            {% set ts = as_timestamp(states('sensor.sun_sunset')) %}
            {% set midnight = as_timestamp(states('sensor.sun_sunset'))
               | timestamp_custom("%Y-%m-%d 00:00:00", true) %}
            {% set midnight_ts = as_timestamp(midnight) %}
            {{ (midnight_ts + (ts - tr)) | timestamp_local }}

      sun_dusktime:
        device_class: timestamp
        friendly_name: 'Today dusktime'
        entity_id:
          - sensor.sun_sunset
          - sensor.sun_dusk
        value_template: >
            {% set ts = as_timestamp(states('sensor.sun_sunset')) %}
            {% set td = as_timestamp(states('sensor.sun_dusk')) %}
            {% set midnight = as_timestamp(states('sensor.sun_sunset'))
               | timestamp_custom("%Y-%m-%d 00:00:00", true) %}
            {% set midnight_ts = as_timestamp(midnight) %}
            {{ (midnight_ts + (td - ts)) | timestamp_local }}
#---------------------------------------------------

This is great thanks for the code, @jabaranauskas!!
One thing I noticed is I’m getting an error when restarting HomeAssistant with the Mid Morning and Mid afternoon functions. It looks like its throwing a type exception and doesn’t like dividing a timestamp by an int. See the error message:

Logger: homeassistant.helpers.event
Source: helpers/template.py:423
First occurred: 11:20:04 AM (2 occurrences)
Last logged: 11:20:04 AM

Error while processing template: Template("{% set tr = as_timestamp(states('sensor.sun_sunrise')) %} {% set tn = as_timestamp(states('sensor.sun_noon')) %} {{ ((tr + tn) / 2.0) | timestamp_local }}")
Error while processing template: Template("{% set ts = as_timestamp(states('sensor.sun_sunset')) %} {% set tn = as_timestamp(states('sensor.sun_noon')) %} {{ ((ts + tn) / 2.0) | timestamp_local }}")
Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 421, in async_render
    render_result = compiled.render(kwargs)
  File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 1090, in render
    self.environment.handle_exception()
  File "/usr/local/lib/python3.8/site-packages/jinja2/environment.py", line 832, in handle_exception
    reraise(*rewrite_traceback_stack(source=source))
  File "/usr/local/lib/python3.8/site-packages/jinja2/_compat.py", line 28, in reraise
    raise value.with_traceback(tb)
  File "<template>", line 1, in top-level template code
TypeError: unsupported operand type(s) for +: 'float' and 'NoneType'

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 518, in async_render_to_info
    render_info._result = self.async_render(variables, **kwargs)
  File "/usr/src/homeassistant/homeassistant/helpers/template.py", line 423, in async_render
    raise TemplateError(err) from err
homeassistant.exceptions.TemplateError: TypeError: unsupported operand type(s) for +: 'float' and 'NoneType' 

However, the sensor is created and I can put all your code into Dev Tools (temeplates) and it works fine w/out errors. Not super concerned, but wondering if others have seen this and what might be causing the error. I found the error in the Configuration>>Logs.

Thanks!

Here is what i ended up doing in my case:

- platform: template
  sensors:
    today_sunset:
      value_template: >
        {% if state_attr('sun.sun', 'rising') %}
          {{ (as_timestamp(state_attr('sun.sun', 'next_setting'))) }}
        {% else %}
          {{ states('sensor.today_sunset') }}
        {% endif %}
    today_sunset_hhmm:
      value_template: "{{ states('sensor.today_sunset')|int|timestamp_custom('%H:%M', true) }}"

This gives you a timestamp and a HH:MM sensor, so with the timestamp version you can add/remove offsets easily for your automations.

I am trying now to avoid custom components as i have too many and want to minimize maintenance

I don’t understand why HA rejected the PR to make the custom component sun2 as part of the default of sun.

1 Like

@jabaranauskas

Do you know how I can convert the sunset ISO time to UTC time?

  - platform: time_date
    display_options:
      - 'date_time_iso'

  - platform: template
    sensors:
      sun_sunset:
        device_class: timestamp
        friendly_name: 'Today Sunset'
        entity_id:
          - sun.sun
          - sensor.date_time_iso
        value_template: >
          {% set day = (as_timestamp(states('sensor.date_time_iso'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% set sday = (as_timestamp(states('sensor.sun_sunset'))
             | timestamp_custom("%Y-%m-%d", true) ) | string %}
          {% if day != sday %}
            {% set time = (as_timestamp(state_attr('sun.sun','next_setting'))
               | timestamp_custom("%H:%M:%S", true) ) | string %}
            {{ (strptime(day+' '+time,'%Y-%m-%d %H:%M:%S') | timestamp_local) }}
          {% else %}
            {{ as_timestamp(states('sensor.sun_sunset')) | timestamp_local }}
          {% endif %}