优化关于时区的问题
This commit is contained in:
+5
-3
@@ -33,7 +33,8 @@ type Cluster struct {
|
|||||||
redis redis.UniversalClient
|
redis redis.UniversalClient
|
||||||
cache *cachex.Cache
|
cache *cachex.Cache
|
||||||
logger Logger
|
logger Logger
|
||||||
keyPrefix string // key前缀
|
keyPrefix string // key前缀
|
||||||
|
location *time.Location // 根据时区计算的时间
|
||||||
|
|
||||||
lockKey string // 全局计算的key
|
lockKey string // 全局计算的key
|
||||||
zsetKey string // 有序集合的key
|
zsetKey string // 有序集合的key
|
||||||
@@ -56,6 +57,7 @@ func InitCluster(ctx context.Context, red redis.UniversalClient, keyPrefix strin
|
|||||||
cache: cachex.NewCache(),
|
cache: cachex.NewCache(),
|
||||||
logger: op.logger,
|
logger: op.logger,
|
||||||
keyPrefix: keyPrefix,
|
keyPrefix: keyPrefix,
|
||||||
|
location: op.location,
|
||||||
lockKey: "timer:cluster_globalLockKey" + keyPrefix, // 定时器的全局锁
|
lockKey: "timer:cluster_globalLockKey" + keyPrefix, // 定时器的全局锁
|
||||||
zsetKey: "timer:cluster_zsetKey" + keyPrefix, // 有序集合
|
zsetKey: "timer:cluster_zsetKey" + keyPrefix, // 有序集合
|
||||||
listKey: "timer:cluster_listKey" + keyPrefix, // 列表
|
listKey: "timer:cluster_listKey" + keyPrefix, // 列表
|
||||||
@@ -208,7 +210,7 @@ func (c *Cluster) addJob(ctx context.Context, taskId string, jobData JobData, ca
|
|||||||
return errors.New("key已存在")
|
return errors.New("key已存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err := GetNextTime(time.Now(), time.Local, jobData)
|
_, err := GetNextTime(time.Now().In(c.location), jobData)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.logger.Errorf(ctx, "获取下次执行时间失败:%s", err.Error())
|
c.logger.Errorf(ctx, "获取下次执行时间失败:%s", err.Error())
|
||||||
return err
|
return err
|
||||||
@@ -259,7 +261,7 @@ func (c *Cluster) getNextTime() {
|
|||||||
clusterWorkerList.Range(func(key, value interface{}) bool {
|
clusterWorkerList.Range(func(key, value interface{}) bool {
|
||||||
val := value.(timerStr)
|
val := value.(timerStr)
|
||||||
|
|
||||||
nextTime, _ := GetNextTime(time.Now(), time.Local, *val.JobData)
|
nextTime, _ := GetNextTime(time.Now().In(c.location), *val.JobData)
|
||||||
|
|
||||||
// fmt.Println(val.ExtendData, val.JobData, nextTime)
|
// fmt.Println(val.ExtendData, val.JobData, nextTime)
|
||||||
|
|
||||||
|
|||||||
+22
-21
@@ -8,21 +8,21 @@ import (
|
|||||||
// 计算该任务下次执行时间
|
// 计算该任务下次执行时间
|
||||||
// @param job *JobData 任务数据
|
// @param job *JobData 任务数据
|
||||||
// @return time.Time 下次执行时间
|
// @return time.Time 下次执行时间
|
||||||
func GetNextTime(t time.Time, loc *time.Location, job JobData) (*time.Time, error) {
|
func GetNextTime(t time.Time, job JobData) (*time.Time, error) {
|
||||||
|
|
||||||
var next time.Time
|
var next time.Time
|
||||||
|
|
||||||
switch job.JobType {
|
switch job.JobType {
|
||||||
case JobTypeEveryMonth:
|
case JobTypeEveryMonth:
|
||||||
next = calculateNextMonthTime(t, job, loc)
|
next = calculateNextMonthTime(t, job)
|
||||||
case JobTypeEveryWeek:
|
case JobTypeEveryWeek:
|
||||||
next = calculateNextWeekTime(t, job, loc)
|
next = calculateNextWeekTime(t, job)
|
||||||
case JobTypeEveryDay:
|
case JobTypeEveryDay:
|
||||||
next = calculateNextDayTime(t, job, loc)
|
next = calculateNextDayTime(t, job)
|
||||||
case JobTypeEveryHour:
|
case JobTypeEveryHour:
|
||||||
next = calculateNextHourTime(t, job, loc)
|
next = calculateNextHourTime(t, job)
|
||||||
case JobTypeEveryMinute:
|
case JobTypeEveryMinute:
|
||||||
next = calculateNextMinuteTime(t, job, loc)
|
next = calculateNextMinuteTime(t, job)
|
||||||
case JobTypeInterval:
|
case JobTypeInterval:
|
||||||
next = calculateNextInterval(t, job)
|
next = calculateNextInterval(t, job)
|
||||||
default:
|
default:
|
||||||
@@ -38,16 +38,17 @@ func calculateNextInterval(t time.Time, job JobData) time.Time {
|
|||||||
return job.BaseTime.Add(job.IntervalTime * time.Duration(cycle+1))
|
return job.BaseTime.Add(job.IntervalTime * time.Duration(cycle+1))
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateNextMonthTime(t time.Time, job JobData, loc *time.Location) time.Time {
|
func calculateNextMonthTime(t time.Time, job JobData) time.Time {
|
||||||
// 判断是否可执行并返回下一个执行时间
|
// 判断是否可执行并返回下一个执行时间
|
||||||
|
|
||||||
if canRun(t, job) {
|
if canRun(t, job) {
|
||||||
return time.Date(t.Year(), t.Month(), job.Day, job.Hour, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), job.Day, job.Hour, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
// 下一个周期(下个月)
|
// 下一个周期(下个月)
|
||||||
return time.Date(t.Year(), t.Month()+1, job.Day, job.Hour, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month()+1, job.Day, job.Hour, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateNextWeekTime(t time.Time, job JobData, loc *time.Location) time.Time {
|
func calculateNextWeekTime(t time.Time, job JobData) time.Time {
|
||||||
weekday := t.Weekday()
|
weekday := t.Weekday()
|
||||||
days := int(job.Weekday - weekday)
|
days := int(job.Weekday - weekday)
|
||||||
if days < 0 {
|
if days < 0 {
|
||||||
@@ -55,37 +56,37 @@ func calculateNextWeekTime(t time.Time, job JobData, loc *time.Location) time.Ti
|
|||||||
}
|
}
|
||||||
// 判断是否可执行并返回下一个执行时间
|
// 判断是否可执行并返回下一个执行时间
|
||||||
if canRun(t, job) {
|
if canRun(t, job) {
|
||||||
return time.Date(t.Year(), t.Month(), t.Day(), job.Hour, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day(), job.Hour, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
// 下一个周期(下周)
|
// 下一个周期(下周)
|
||||||
return time.Date(t.Year(), t.Month(), t.Day()+days+7, job.Hour, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day()+days+7, job.Hour, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateNextDayTime(t time.Time, job JobData, loc *time.Location) time.Time {
|
func calculateNextDayTime(t time.Time, job JobData) time.Time {
|
||||||
// 判断是否可执行并返回下一个执行时间
|
// 判断是否可执行并返回下一个执行时间
|
||||||
if canRun(t, job) {
|
if canRun(t, job) {
|
||||||
return time.Date(t.Year(), t.Month(), t.Day(), job.Hour, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day(), job.Hour, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
// 下一个周期(明天)
|
// 下一个周期(明天)
|
||||||
return time.Date(t.Year(), t.Month(), t.Day()+1, job.Hour, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day()+1, job.Hour, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateNextHourTime(t time.Time, job JobData, loc *time.Location) time.Time {
|
func calculateNextHourTime(t time.Time, job JobData) time.Time {
|
||||||
// 判断是否可执行并返回下一个执行时间
|
// 判断是否可执行并返回下一个执行时间
|
||||||
if canRun(t, job) {
|
if canRun(t, job) {
|
||||||
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
// 下一个周期(下个小时)
|
// 下一个周期(下个小时)
|
||||||
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour()+1, job.Minute, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour()+1, job.Minute, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
|
|
||||||
func calculateNextMinuteTime(t time.Time, job JobData, loc *time.Location) time.Time {
|
func calculateNextMinuteTime(t time.Time, job JobData) time.Time {
|
||||||
// 判断是否可执行并返回下一个执行时间
|
// 判断是否可执行并返回下一个执行时间
|
||||||
if canRun(t, job) {
|
if canRun(t, job) {
|
||||||
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute(), job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
// 下一个周期(下分钟)
|
// 下一个周期(下分钟)
|
||||||
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()+1, job.Second, 0, loc)
|
return time.Date(t.Year(), t.Month(), t.Day(), t.Hour(), t.Minute()+1, job.Second, 0, t.Location())
|
||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否本周期可以运行
|
// 检查是否本周期可以运行
|
||||||
|
|||||||
+2
-2
@@ -92,8 +92,8 @@ func TestGetNextTime(t *testing.T) {
|
|||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.name, func(t *testing.T) {
|
t.Run(test.name, func(t *testing.T) {
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
loc := time.FixedZone("CST", 8*3600)
|
// loc := time.FixedZone("CST", 8*3600)
|
||||||
nextTime, err := timerx.GetNextTime(now,loc,test.job)
|
nextTime, err := timerx.GetNextTime(now, test.job)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if test.expectedError == nil || err.Error() != test.expectedError.Error() {
|
if test.expectedError == nil || err.Error() != test.expectedError.Error() {
|
||||||
t.Errorf("Expected error: %v, Got error: %v", test.expectedError, err)
|
t.Errorf("Expected error: %v, Got error: %v", test.expectedError, err)
|
||||||
|
|||||||
@@ -1,12 +1,16 @@
|
|||||||
package timerx
|
package timerx
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
type Options struct {
|
type Options struct {
|
||||||
logger Logger
|
logger Logger
|
||||||
|
location *time.Location
|
||||||
}
|
}
|
||||||
|
|
||||||
func defaultOptions() Options {
|
func defaultOptions() Options {
|
||||||
return Options{
|
return Options{
|
||||||
logger: NewLogger(),
|
logger: NewLogger(),
|
||||||
|
location: time.Local,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -28,8 +32,8 @@ func SetLogger(log Logger) Option {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 设定时区
|
// 设定时区
|
||||||
func SetTimeZone(zone string) Option {
|
func SetTimeZone(zone *time.Location) Option {
|
||||||
return func(o *Options) {
|
return func(o *Options) {
|
||||||
// todo
|
o.location = zone
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,8 +24,9 @@ var singleTimerIndex int // 当前定时数目
|
|||||||
var singleOnceLimit sync.Once // 实现单例
|
var singleOnceLimit sync.Once // 实现单例
|
||||||
|
|
||||||
type Single struct {
|
type Single struct {
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
logger Logger
|
logger Logger
|
||||||
|
location *time.Location
|
||||||
}
|
}
|
||||||
|
|
||||||
var sin *Single = nil
|
var sin *Single = nil
|
||||||
@@ -40,8 +41,9 @@ func InitSingle(ctx context.Context, opts ...Option) *Single {
|
|||||||
op := newOptions(opts...)
|
op := newOptions(opts...)
|
||||||
|
|
||||||
sin = &Single{
|
sin = &Single{
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
logger: op.logger,
|
logger: op.logger,
|
||||||
|
location: op.location,
|
||||||
}
|
}
|
||||||
|
|
||||||
timer := time.NewTicker(time.Millisecond * 200)
|
timer := time.NewTicker(time.Millisecond * 200)
|
||||||
@@ -55,7 +57,7 @@ func InitSingle(ctx context.Context, opts ...Option) *Single {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 迭代定时器
|
// 迭代定时器
|
||||||
sin.iterator(ctx, t)
|
sin.iterator(ctx)
|
||||||
// fmt.Println("timer: 执行")
|
// fmt.Println("timer: 执行")
|
||||||
case <-ctx.Done():
|
case <-ctx.Done():
|
||||||
// 跳出循环
|
// 跳出循环
|
||||||
@@ -185,9 +187,7 @@ func (c *Single) AddSpace(ctx context.Context, taskId string, spaceTime time.Dur
|
|||||||
func (l *Single) addJob(ctx context.Context, jobData JobData, call callback, extend interface{}) (int, error) {
|
func (l *Single) addJob(ctx context.Context, jobData JobData, call callback, extend interface{}) (int, error) {
|
||||||
singleTimerIndex += 1
|
singleTimerIndex += 1
|
||||||
|
|
||||||
nowTime := time.Now()
|
_, err := GetNextTime(time.Now().In(l.location), jobData)
|
||||||
|
|
||||||
_, err := GetNextTime(nowTime, time.Local, jobData)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
l.logger.Errorf(ctx, "获取下次执行时间失败:%s", err.Error())
|
l.logger.Errorf(ctx, "获取下次执行时间失败:%s", err.Error())
|
||||||
return 0, err
|
return 0, err
|
||||||
@@ -211,7 +211,9 @@ func (s *Single) Del(index int) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 迭代定时器列表
|
// 迭代定时器列表
|
||||||
func (s *Single) iterator(ctx context.Context, nowTime time.Time) {
|
func (s *Single) iterator(ctx context.Context) {
|
||||||
|
|
||||||
|
nowTime := time.Now().In(s.location)
|
||||||
|
|
||||||
// 默认5秒后(如果没有值就暂停进来5秒)
|
// 默认5秒后(如果没有值就暂停进来5秒)
|
||||||
newNextTime := nowTime.Add(time.Second * 5)
|
newNextTime := nowTime.Add(time.Second * 5)
|
||||||
@@ -223,7 +225,7 @@ func (s *Single) iterator(ctx context.Context, nowTime time.Time) {
|
|||||||
|
|
||||||
if timeStr.JobData.NextTime.Before(nowTime) || timeStr.JobData.NextTime.Equal(nowTime) {
|
if timeStr.JobData.NextTime.Before(nowTime) || timeStr.JobData.NextTime.Equal(nowTime) {
|
||||||
// 可执行
|
// 可执行
|
||||||
nextTime, _ := GetNextTime(nowTime, time.Local, *timeStr.JobData)
|
nextTime, _ := GetNextTime(nowTime, *timeStr.JobData)
|
||||||
timeStr.JobData.NextTime = *nextTime
|
timeStr.JobData.NextTime = *nextTime
|
||||||
|
|
||||||
if index == 1 {
|
if index == 1 {
|
||||||
|
|||||||
Reference in New Issue
Block a user