50 lines
1.5 KiB
Go
50 lines
1.5 KiB
Go
|
|
package service
|
|||
|
|
|
|||
|
|
import (
|
|||
|
|
"strconv"
|
|||
|
|
"strings"
|
|||
|
|
"time"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
// parseClock 解析 HH:MM,非法输入回退 09:00。
|
|||
|
|
func parseClock(at string) (int, int) {
|
|||
|
|
parts := strings.SplitN(at, ":", 2)
|
|||
|
|
if len(parts) != 2 {
|
|||
|
|
return 9, 0
|
|||
|
|
}
|
|||
|
|
h, e1 := strconv.Atoi(parts[0])
|
|||
|
|
m, e2 := strconv.Atoi(parts[1])
|
|||
|
|
if e1 != nil || e2 != nil || h < 0 || h > 23 || m < 0 || m > 59 {
|
|||
|
|
return 9, 0
|
|||
|
|
}
|
|||
|
|
return h, m
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// DigestDue 判断团队日报摘要是否到达自动生成时间:now 已过当天 at(HH:MM)。
|
|||
|
|
func DigestDue(at string, now time.Time) bool {
|
|||
|
|
hh, mm := parseClock(at)
|
|||
|
|
due := time.Date(now.Year(), now.Month(), now.Day(), hh, mm, 0, 0, now.Location())
|
|||
|
|
return !now.Before(due)
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// NextAutoUpdate 计算下一次自动更新的时间点(纯函数,便于测试)。
|
|||
|
|
// mode: daily | everyNDays | everyNHours;at 为 HH:MM;last 为上次执行时间(调用方保证非零)。
|
|||
|
|
func NextAutoUpdate(mode string, interval int, at string, last, now time.Time) time.Time {
|
|||
|
|
if interval < 1 {
|
|||
|
|
interval = 1
|
|||
|
|
}
|
|||
|
|
hh, mm := parseClock(at)
|
|||
|
|
switch mode {
|
|||
|
|
case "everyNHours":
|
|||
|
|
return last.Add(time.Duration(interval) * time.Hour)
|
|||
|
|
case "everyNDays":
|
|||
|
|
return time.Date(last.Year(), last.Month(), last.Day(), hh, mm, 0, 0, last.Location()).AddDate(0, 0, interval)
|
|||
|
|
default: // daily:今天的 HH:MM;若上次已在该时点之后执行过,则推到明天。
|
|||
|
|
t := time.Date(now.Year(), now.Month(), now.Day(), hh, mm, 0, 0, now.Location())
|
|||
|
|
if !last.Before(t) {
|
|||
|
|
t = t.AddDate(0, 0, 1)
|
|||
|
|
}
|
|||
|
|
return t
|
|||
|
|
}
|
|||
|
|
}
|