diff --git a/timer.go b/timer.go index 9a2313b..e2ae8b4 100644 --- a/timer.go +++ b/timer.go @@ -2,6 +2,7 @@ package startimer import ( "context" + "encoding/json" "errors" "sort" "sync" @@ -96,6 +97,40 @@ func (t *StarTimer) NextTimer() time.Time { return t.nextDate } +func (t *StarTimer) NextTimerAfterDate(date time.Time) time.Time { + return t.parseNextDate(date, true) +} + +func (t *StarTimer) ExportRepeats() (string, error) { + var rep []Repeats + for _, r := range t.repeat { + rep = append(rep, *r) + } + data, err := json.Marshal(rep) + if err != nil { + return "", err + } + return string(data), nil +} + +func (t *StarTimer) ImportRepeats(r string) error { + t.mu.Lock() + defer t.mu.Unlock() + if t.running { + return errors.New("coonot import repeats to already running timer") + } + var rep []Repeats + err := json.Unmarshal([]byte(r), &rep) + if err != nil { + return err + } + t.repeat = make([]*Repeats, 0, len(rep)) + for _, v := range rep { + t.repeat = append(t.repeat, &v) + } + return nil +} + func (t *StarTimer) BaseDate() time.Time { return t.base } @@ -113,7 +148,7 @@ func (t *StarTimer) Run() error { if t.running { return nil } - t.nextDate = t.parseNextDate(t.base) + t.nextDate = t.parseNextDate(time.Now(), false) if t.nextDate.Before(time.Now()) { return errors.New("Invalid Timer Options,Please Check") } @@ -127,7 +162,7 @@ func (t *StarTimer) Run() error { t.mu.Unlock() select { case <-t.timer.C: - t.nextDate = t.parseNextDate(t.nextDate) + t.nextDate = t.parseNextDate(t.nextDate, false) if t.nextDate.Before(now) { t.Stop() } @@ -145,7 +180,7 @@ func (t *StarTimer) Run() error { return nil } -func (t *StarTimer) parseNextDate(base time.Time) time.Time { +func (t *StarTimer) parseNextDate(base time.Time, isMock bool) time.Time { if len(t.repeat) == 0 { return time.Time{} } @@ -155,7 +190,7 @@ func (t *StarTimer) parseNextDate(base time.Time) time.Time { continue } if d.Every { - dates = append(dates, t.parseEveryNextDate(base, d)...) + dates = append(dates, t.parseEveryNextDate(base, d, isMock)...) } else { dates = append(dates, t.parseStaticNextDate(base, d)) } @@ -226,13 +261,15 @@ func (t *StarTimer) parseStaticNextDate(base time.Time, r *Repeats) time.Time { return target } -func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time { +func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats, isMock bool) []time.Time { var res []time.Time if r.Every { //定期日期 for idx, d := range r.Repeat { if d.baseDate.Unix() == -62135596800 { d.baseDate = t.base - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } } if d.baseDate.After(target) { res = append(res, d.baseDate) @@ -243,7 +280,9 @@ func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time for { d.baseDate = d.baseDate.Add(time.Second * time.Duration(int(d.Value))) if d.baseDate.After(target) { - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } break } } @@ -252,7 +291,9 @@ func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time for { d.baseDate = d.baseDate.Add(time.Minute * time.Duration(int(d.Value))) if d.baseDate.After(target) { - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } break } } @@ -261,7 +302,9 @@ func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time for { d.baseDate = d.baseDate.Add(time.Hour * time.Duration(int(d.Value))) if d.baseDate.After(target) { - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } break } } @@ -270,7 +313,9 @@ func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time for { d.baseDate = d.baseDate.Add(time.Hour * 24 * time.Duration(int(d.Value))) if d.baseDate.After(target) { - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } break } } @@ -279,7 +324,9 @@ func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time for { d.baseDate = d.baseDate.AddDate(0, int(d.Value), 0) if d.baseDate.After(target) { - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } break } } @@ -288,7 +335,9 @@ func (t *StarTimer) parseEveryNextDate(target time.Time, r *Repeats) []time.Time for { d.baseDate = d.baseDate.AddDate(int(d.Value), 0, 0) if d.baseDate.After(target) { - r.Repeat[idx] = d + if !isMock { + r.Repeat[idx] = d + } break } } diff --git a/typed.go b/typed.go index 9fbdcd9..6f0a101 100644 --- a/typed.go +++ b/typed.go @@ -18,14 +18,14 @@ const ( ) type Repeats struct { - Repeat []Repeat - Every bool // false=static true=every + Repeat []Repeat `json:"repeat"` + Every bool `json:"every"` // false=static true=every } type Repeat struct { - Unit Unit + Unit Unit `json:"unit"` baseDate time.Time - Value uint32 + Value uint32 `json:"value"` } type StarTimer struct { @@ -46,8 +46,8 @@ type TimerOption struct { idx uint8 repeats *Repeats tasks func() - date time.Time - repeat Repeat + date time.Time + repeat Repeat } func WithRepeats(r *Repeats) TimerOptions {