Schedule backups in local time instead of UTC (0.66.0)
Schedule times were UTC, so a nightly 03:00 backup had to be entered as 01:00 or 02:00 depending on the season, and moved by an hour twice a year. Each schedule now has an IANA time zone, preset in the form to the browser's (e.g. Europe/Berlin), and its hour/minute/weekday are wall-clock time there. compute_next_run builds each candidate day from its date in that zone rather than adding 24 hours, so the time stays put across daylight saving changes; a time skipped by the spring change runs an hour later that day. next_run is still stored as naive UTC. - Existing schedules default to UTC and keep their run times until edited. - The API validates the zone and hour/minute/weekday ranges (400) instead of silently wrapping them. - tzdata is a dependency: the slim base image has no system tz database. Tests cover Berlin winter and summer time, both 2026 change days, the skipped hour, a weekly run across the UTC date line, hourly at a +5:30 offset, the UTC fallback and the API checks. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8a0d673798
commit
9a357d2b92
10 files changed
+192
-27
No files matched your search
@@ -30,9 +30,12 @@ class BackupSchedule(SQLModel, table=True):
|
||||
all_stacks: bool = False
|
||||
destination_id: int
|
||||
frequency: str = "daily" # one of FREQUENCIES
|
||||
hour: int = 3 # UTC, used for daily/weekly
|
||||
hour: int = 3 # wall-clock time in ``timezone``, used for daily/weekly
|
||||
minute: int = 0
|
||||
weekday: int = 0 # 0=Mon .. 6=Sun, used for weekly
|
||||
#: IANA zone the time is in ("Europe/Berlin"). Schedules from before
|
||||
#: 0.66.0 were UTC and stay so until edited.
|
||||
timezone: str = "UTC"
|
||||
include_volumes: bool = True
|
||||
stop_first: bool = True
|
||||
keep: int = 7 # retention: keep newest N for this stack on the dest (0 = all)
|
||||
@@ -88,6 +91,7 @@ class ScheduleCreate(SQLModel):
|
||||
hour: int = 3
|
||||
minute: int = 0
|
||||
weekday: int = 0
|
||||
timezone: str = "UTC"
|
||||
include_volumes: bool = True
|
||||
stop_first: bool = True
|
||||
keep: int = 7
|
||||
@@ -102,6 +106,7 @@ class ScheduleUpdate(SQLModel):
|
||||
hour: Optional[int] = None
|
||||
minute: Optional[int] = None
|
||||
weekday: Optional[int] = None
|
||||
timezone: Optional[str] = None
|
||||
include_volumes: Optional[bool] = None
|
||||
stop_first: Optional[bool] = None
|
||||
keep: Optional[int] = None
|
||||
@@ -120,6 +125,7 @@ class ScheduleRead(SQLModel):
|
||||
hour: int
|
||||
minute: int
|
||||
weekday: int
|
||||
timezone: str
|
||||
include_volumes: bool
|
||||
stop_first: bool
|
||||
keep: int
|
||||
|
||||
Reference in new issue
Block a user