Skip to content

Bug: run_at_sunrise/sunset schedules at wrong time due to timezone handling in make_naive() #2512

@tblank1024

Description

@tblank1024

What happened?

Summary

Sun-based timers (run_at_sunrise(), run_at_sunset()) trigger at incorrect times when in non-UTC time zone due to a bug in the make_naive() method that strips timezone information instead of converting UTC to local time.

Environment

  • AppDaemon: 4.5.12
  • Python: 3.12.12
  • Timezone: America/Los_Angeles (PST/PDT, UTC-8/-7)
  • Config files set equivalently in both HA and Appdaemon
  • astral: 3.2

Expected Behavior

A timer scheduled with run_at_sunrise() should trigger at the actual local sunrise time (e.g., 7:56 AM PST).

Actual Behavior

Timers trigger approximately 16 hours late (e.g., 11:50 PM instead of 7:56 AM), creating an apparent +8 hour offset that wraps around to the previous day.

Root Cause

In appdaemon/scheduler.py at line 967, the make_naive() method incorrectly strips timezone information:

def make_naive(self, dt: datetime) -> datetime:
    return dt.replace(tzinfo=None)  # Simply strips timezone!

The scheduler correctly stores timezone-aware UTC datetimes in self.schedule[name][handle]["timestamp"]. However, when info_timer() (line 721) and get_scheduler_entries() (line 734) call make_naive() for display purposes, this creates a naive datetime with UTC time values. When this naive datetime is later interpreted as local time, it causes incorrect time display.

Example:

  • Actual stored value: 2025-12-27 07:50:44+00:00 (UTC)
  • After make_naive(): datetime(2025, 12, 27, 7, 50, 44) (naive, but still UTC values)
  • When interpreted as local PST: appears as 7:50 AM PST, but logging converts back to UTC adding +8 hours
  • Result: Displays as 23:50 (11:50 PM) previous day

Proposed Fix

Modify make_naive() to convert from UTC to local timezone before stripping timezone info:

def make_naive(self, dt: datetime) -> datetime:
    """Convert a timezone-aware datetime to a naive datetime in local timezone.
    
    This is used for display purposes only. The scheduler internally works
    with timezone-aware UTC datetimes.
    """
    # Convert from UTC to local timezone, then strip timezone info
    local_dt = dt.astimezone(self.AD.tz)
    return local_dt.replace(tzinfo=None)

Verification approach used

Created diagnostic app that showed:

  • Astral library correctly calculates: 2025-12-26 07:56:39-08:00 (sunrise in PST)
  • Scheduler stores: 2025-12-27 07:50:44+00:00 (correct UTC conversion)
  • info_timer() returns: datetime(2025, 12, 27, 7, 50, 44) (naive, incorrect)
  • Logs show: 2025-12-26 23:50:44 (wrong by 16 hours)

Version

4.5.12

Installation type

Home Assistant add-on

Relevant log output

Relevant code in the app or config file that caused the issue

Anything else?

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    issueSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions