Skip to content

Commit 4426428

Browse files
committed
feat: Add timezone support for scheduler next run display - Add getConfiguredTimezone() helper function with priority TZ env > config.timezone > UTC - Display next run times in configured timezone instead of local time - Enhanced logging with timezone information
1 parent fd5f48e commit 4426428

File tree

1 file changed

+54
-9
lines changed

1 file changed

+54
-9
lines changed

cmd/export_trakt/main.go

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,41 @@ func runExportOnce(cfg *config.Config, log logger.Logger, exportType, exportMode
351351
})
352352
}
353353

354+
// getConfiguredTimezone returns the configured timezone or UTC as fallback
355+
func getConfiguredTimezone(cfg *config.Config, log logger.Logger) *time.Location {
356+
// Try environment variable first (Docker TZ)
357+
if tz := os.Getenv("TZ"); tz != "" {
358+
if loc, err := time.LoadLocation(tz); err == nil {
359+
log.Info("scheduler.using_env_timezone", map[string]interface{}{
360+
"timezone": tz,
361+
})
362+
return loc
363+
}
364+
log.Warn("scheduler.invalid_env_timezone", map[string]interface{}{
365+
"timezone": tz,
366+
})
367+
}
368+
369+
// Try config timezone
370+
if cfg.Export.Timezone != "" {
371+
if loc, err := time.LoadLocation(cfg.Export.Timezone); err == nil {
372+
log.Info("scheduler.using_config_timezone", map[string]interface{}{
373+
"timezone": cfg.Export.Timezone,
374+
})
375+
return loc
376+
}
377+
log.Warn("scheduler.invalid_config_timezone", map[string]interface{}{
378+
"timezone": cfg.Export.Timezone,
379+
})
380+
}
381+
382+
// Fallback to UTC
383+
log.Info("scheduler.using_default_timezone", map[string]interface{}{
384+
"timezone": "UTC",
385+
})
386+
return time.UTC
387+
}
388+
354389
// runWithSchedule sets up a cron scheduler and runs the export according to the schedule
355390
func runWithSchedule(cfg *config.Config, log logger.Logger, schedule, exportType, exportMode string) {
356391
log.Info("scheduler.initializing", map[string]interface{}{
@@ -373,6 +408,9 @@ func runWithSchedule(cfg *config.Config, log logger.Logger, schedule, exportType
373408
})
374409
}
375410

411+
// Get configured timezone for display
412+
configuredTZ := getConfiguredTimezone(cfg, log)
413+
376414
// Validate cron expression
377415
cronParser := cron.NewParser(cron.Minute | cron.Hour | cron.Dom | cron.Month | cron.Dow)
378416
_, err := cronParser.Parse(schedule)
@@ -419,7 +457,7 @@ func runWithSchedule(cfg *config.Config, log logger.Logger, schedule, exportType
419457
"export_type": exportType,
420458
"export_mode": exportMode,
421459
"duration": duration.String(),
422-
"next_run": c.Entries()[0].Next.Format(time.RFC3339),
460+
"next_run": c.Entries()[0].Next.In(configuredTZ).Format(time.RFC3339),
423461
})
424462
})
425463

@@ -441,38 +479,45 @@ func runWithSchedule(cfg *config.Config, log logger.Logger, schedule, exportType
441479
c.Start()
442480
log.Info("scheduler.cron_started", nil)
443481

444-
// Get the next run time
482+
// Get the next run time and display in configured timezone
445483
entries := c.Entries()
446484
if len(entries) > 0 {
447485
nextRun := entries[0].Next
486+
nextRunInTZ := nextRun.In(configuredTZ)
487+
448488
log.Info("scheduler.started", map[string]interface{}{
449-
"schedule": schedule,
450-
"entry_id": entryID,
451-
"next_run": nextRun.Format(time.RFC3339),
452-
"next_run_local": nextRun.Format("2006-01-02 15:04:05 MST"),
489+
"schedule": schedule,
490+
"entry_id": entryID,
491+
"next_run": nextRun.Format(time.RFC3339),
492+
"next_run_local": nextRunInTZ.Format("2006-01-02 15:04:05 MST"),
493+
"timezone": configuredTZ.String(),
453494
})
454495
fmt.Printf("Scheduler started successfully!\n")
455496
fmt.Printf("Schedule: %s\n", schedule)
456497
fmt.Printf("Export Type: %s\n", exportType)
457498
fmt.Printf("Export Mode: %s\n", exportMode)
458-
fmt.Printf("Next run: %s\n", nextRun.Format("2006-01-02 15:04:05 MST"))
499+
fmt.Printf("Timezone: %s\n", configuredTZ.String())
500+
fmt.Printf("Next run: %s\n", nextRunInTZ.Format("2006-01-02 15:04:05 MST"))
459501

460-
// Log upcoming executions for the next hour
502+
// Log upcoming executions for the next hour in configured timezone
461503
now := time.Now()
462504
oneHourLater := now.Add(time.Hour)
463505
log.Info("scheduler.upcoming_executions_preview", map[string]interface{}{
464506
"next_hour_from": now.Format(time.RFC3339),
465507
"next_hour_to": oneHourLater.Format(time.RFC3339),
508+
"timezone": configuredTZ.String(),
466509
})
467510

468511
count := 0
469512
if len(entries) > 0 {
470513
entry := entries[0]
471514
nextExec := entry.Next
472515
for nextExec.Before(oneHourLater) && count < 10 {
516+
nextExecInTZ := nextExec.In(configuredTZ)
473517
log.Info("scheduler.upcoming_execution", map[string]interface{}{
474-
"execution_time": nextExec.Format("2006-01-02 15:04:05 MST"),
518+
"execution_time": nextExecInTZ.Format("2006-01-02 15:04:05 MST"),
475519
"in_minutes": int(time.Until(nextExec).Minutes()),
520+
"timezone": configuredTZ.String(),
476521
})
477522
// Calculate next execution after this one
478523
schedule, _ := cronParser.Parse(schedule)

0 commit comments

Comments
 (0)