fix(time): konfigurierbare Fach-Zeitzone statt UTC/OS-Local fuer alle Datumsangaben
Lieferbericht zeigte UTC (08.09. 22:54 statt 09.09. 00:54): renderer.dt() formatierte DateTime<Utc> ohne Umrechnung. Weitere Stellen hingen an chrono::Local (OS-Zone des Hosts) bzw. hardcodiertem 'Europe/Berlin'. Neu: server.timezone (IANA, Default Europe/Berlin, chrono-tz) und durchgaengig UTC-Instant -> konfigurierte Zone: - Lieferbericht: alle Zeitstempel (Abgeschlossen, Notizen, Scans, erzeugt am) - Belegansicht (fmt_datetime) - ERP-Rueckschreibung delivered_at (Wanduhrzeit) - 'heute'-Ableitung: /me/tours, /dev/resync, /admin/import-erp, Import-Cron + Startup-Catch-up - Completion-Repo: AT TIME ZONE als Bind-Param statt Literal Speicherung bleibt UTC (TIMESTAMPTZ / DateTime<Utc>) - nur Anzeige und Kalendertag-Ableitung nutzen die Zone. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@ -17,6 +17,7 @@ async-trait.workspace = true
|
||||
thiserror.workspace = true
|
||||
uuid.workspace = true
|
||||
chrono.workspace = true
|
||||
chrono-tz.workspace = true
|
||||
sha2.workspace = true
|
||||
imagesize.workspace = true
|
||||
utoipa = { workspace = true, optional = true }
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::{Local, NaiveDate};
|
||||
use chrono::{NaiveDate, Utc};
|
||||
use chrono_tz::Tz;
|
||||
|
||||
use crate::dto::TourSummary;
|
||||
use crate::error::ApplicationError;
|
||||
@ -22,13 +23,20 @@ use crate::ports::TourRepository;
|
||||
pub struct ListMyToursTodayUseCase {
|
||||
repository: Arc<dyn TourRepository>,
|
||||
today_override: Option<NaiveDate>,
|
||||
/// Fach-Zeitzone (`server.timezone`), in der „heute" bestimmt wird.
|
||||
tz: Tz,
|
||||
}
|
||||
|
||||
impl ListMyToursTodayUseCase {
|
||||
pub fn new(repository: Arc<dyn TourRepository>, today_override: Option<NaiveDate>) -> Self {
|
||||
pub fn new(
|
||||
repository: Arc<dyn TourRepository>,
|
||||
today_override: Option<NaiveDate>,
|
||||
tz: Tz,
|
||||
) -> Self {
|
||||
Self {
|
||||
repository,
|
||||
today_override,
|
||||
tz,
|
||||
}
|
||||
}
|
||||
|
||||
@ -37,14 +45,15 @@ impl ListMyToursTodayUseCase {
|
||||
personalnummer: i64,
|
||||
requested_date: Option<NaiveDate>,
|
||||
) -> Result<Vec<TourSummary>, ApplicationError> {
|
||||
// Bewusst Local statt Utc: der Tagesumschlag muss sich nach der
|
||||
// Ortszeit des Fahrers richten. Mit Utc wechselt "heute" erst um
|
||||
// 02:00 Ortszeit (CEST = UTC+2) — bis dahin sähe der Fahrer nach
|
||||
// Mitternacht noch die Touren von gestern. Der Server läuft in
|
||||
// Europe/Vienna, daher ist Local hier korrekt.
|
||||
// Der Tagesumschlag muss sich nach der Ortszeit des Fahrers richten:
|
||||
// mit reinem Utc wechselte "heute" erst um 02:00 Ortszeit (CEST =
|
||||
// UTC+2) — bis dahin sähe der Fahrer nach Mitternacht noch die Touren
|
||||
// von gestern. Daher der UTC-Instant → konfigurierte Fach-Zeitzone
|
||||
// (`server.timezone`) → Kalendertag. Bewusst NICHT `chrono::Local`:
|
||||
// das wäre die OS-Zone des Hosts und damit einstellungsabhängig.
|
||||
let date = requested_date
|
||||
.or(self.today_override)
|
||||
.unwrap_or_else(|| Local::now().date_naive());
|
||||
.unwrap_or_else(|| Utc::now().with_timezone(&self.tz).date_naive());
|
||||
self.repository
|
||||
.find_today_for_driver(personalnummer, date)
|
||||
.await
|
||||
|
||||
Reference in New Issue
Block a user