diff --git a/api/alarms.go b/api/alarms.go index 59dfe98..e27771c 100644 --- a/api/alarms.go +++ b/api/alarms.go @@ -13,7 +13,7 @@ import ( func declareAlarmsRoutes(cfg *config.Config, db *reveil.LevelDBStorage, resetTimer func(), router *gin.RouterGroup) { router.GET("/alarms/next", func(c *gin.Context) { - alarm, err := reveil.GetNextAlarm(db) + alarm, err := reveil.GetNextAlarm(cfg, db) if err != nil { c.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"errmsg": err.Error()}) return @@ -200,8 +200,8 @@ func declareAlarmsRoutes(cfg *config.Config, db *reveil.LevelDBStorage, resetTim repeatedAlarmsRoutes.GET("", func(c *gin.Context) { alarm := c.MustGet("alarm").(*reveil.AlarmRepeated) - alarm.FillExcepts(db) - alarm.NextTime = alarm.GetNextOccurence(db) + alarm.FillExcepts(cfg, db) + alarm.NextTime = alarm.GetNextOccurence(cfg, db) c.JSON(http.StatusOK, alarm) }) diff --git a/app.go b/app.go index 778abd6..0867a7e 100644 --- a/app.go +++ b/app.go @@ -64,6 +64,7 @@ func (app *App) Start() { Handler: app.router, } + log.Println("Current timezone:", app.cfg.Timezone.String()) app.ResetTimer() log.Printf("Ready, listening on %s\n", app.cfg.Bind) @@ -78,7 +79,7 @@ func (app *App) ResetTimer() { app.nextAlarm = nil } - if na, err := reveil.GetNextAlarm(app.db); err == nil && na != nil { + if na, err := reveil.GetNextAlarm(app.cfg, app.db); err == nil && na != nil { app.nextAlarm = time.AfterFunc(time.Until(*na), func() { app.nextAlarm = nil reveil.RemoveOldAlarmsSingle(app.db) diff --git a/config/cli.go b/config/cli.go index 1894daa..4677a69 100644 --- a/config/cli.go +++ b/config/cli.go @@ -17,6 +17,7 @@ func (c *Config) declareFlags() { flag.StringVar(&c.ActionsDir, "actions-dir", c.ActionsDir, "Path to the directory containing the actions") flag.StringVar(&c.RoutinesDir, "routines-dir", c.RoutinesDir, "Path to the directory containing the routines") flag.IntVar(&c.SampleRate, "samplerate", c.SampleRate, "Samplerate for unifying output stream") + flag.Var(&c.Timezone, "timezone", "Timezone to use when dealing with times") // Others flags are declared in some other files when they need specials configurations } diff --git a/config/config.go b/config/config.go index 26fe5c1..26f791a 100644 --- a/config/config.go +++ b/config/config.go @@ -18,6 +18,7 @@ type Config struct { ActionsDir string RoutinesDir string + Timezone Timezone SampleRate int } diff --git a/config/custom.go b/config/custom.go index 716a2f7..be0437b 100644 --- a/config/custom.go +++ b/config/custom.go @@ -3,6 +3,7 @@ package config import ( "encoding/base64" "net/url" + "time" ) type JWTSecretKey []byte @@ -42,3 +43,33 @@ func (i *URL) Set(value string) error { i.URL = u return nil } + +type Timezone struct { + tz *time.Location +} + +func (tz *Timezone) GetLocation() *time.Location { + if tz.tz != nil { + return tz.tz + } else { + return time.Local + } +} + +func (tz *Timezone) String() string { + if tz.tz != nil { + return tz.tz.String() + } else { + return time.Local.String() + } +} + +func (tz *Timezone) Set(value string) error { + newtz, err := time.LoadLocation(value) + if err != nil { + return err + } + + tz.tz = newtz + return nil +} diff --git a/model/alarm.go b/model/alarm.go index e6a8bbd..12920b9 100644 --- a/model/alarm.go +++ b/model/alarm.go @@ -4,6 +4,8 @@ import ( "fmt" "sort" "time" + + "git.nemunai.re/nemunaire/reveil/config" ) type Date time.Time @@ -38,7 +40,7 @@ func (h *Hour) UnmarshalJSON(src []byte) error { return nil } -func GetNextAlarm(db *LevelDBStorage) (*time.Time, error) { +func GetNextAlarm(cfg *config.Config, db *LevelDBStorage) (*time.Time, error) { alarmsRepeated, err := GetAlarmsRepeated(db) if err != nil { return nil, err @@ -46,7 +48,7 @@ func GetNextAlarm(db *LevelDBStorage) (*time.Time, error) { var closestAlarm *time.Time for _, alarm := range alarmsRepeated { - next := alarm.GetNextOccurence(db) + next := alarm.GetNextOccurence(cfg, db) if next != nil && (closestAlarm == nil || closestAlarm.After(*next)) { closestAlarm = next } @@ -92,7 +94,7 @@ type AlarmRepeated struct { NextTime *time.Time `json:"next_time,omitempty"` } -func (a *AlarmRepeated) FillExcepts(db *LevelDBStorage) error { +func (a *AlarmRepeated) FillExcepts(cfg *config.Config, db *LevelDBStorage) error { if a.IgnoreExceptions { return nil } @@ -112,7 +114,7 @@ func (a *AlarmRepeated) FillExcepts(db *LevelDBStorage) error { end := time.Time(*exception.End).AddDate(0, 0, 1) for t := time.Time(*exception.Start); end.After(t); t = t.AddDate(0, 0, 1) { if t.Weekday() == a.Weekday { - a.Excepts = append(a.Excepts, time.Date(t.Year(), t.Month(), t.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, now.Location())) + a.Excepts = append(a.Excepts, time.Date(t.Year(), t.Month(), t.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, cfg.Timezone.GetLocation())) t.AddDate(0, 0, 6) } } @@ -123,14 +125,14 @@ func (a *AlarmRepeated) FillExcepts(db *LevelDBStorage) error { return nil } -func (a *AlarmRepeated) GetNextOccurence(db *LevelDBStorage) *time.Time { +func (a *AlarmRepeated) GetNextOccurence(cfg *config.Config, db *LevelDBStorage) *time.Time { if len(a.Excepts) == 0 { - a.FillExcepts(db) + a.FillExcepts(cfg, db) } now := time.Now() - today := time.Date(now.Year(), now.Month(), now.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, now.Location()) + today := time.Date(now.Year(), now.Month(), now.Day(), time.Time(*a.StartTime).Hour(), time.Time(*a.StartTime).Minute(), time.Time(*a.StartTime).Second(), 0, cfg.Timezone.GetLocation()) if now.After(today) { today = today.AddDate(0, 0, 1) }