golang time.AddDate的问题

| 分类 工作日志  | 标签 galang 

周末线上出现一个问题,3月份的订单没有算出来,从数据库表数据上看,订单数据已经是完成状态,但数据为空。

业务上的逻辑是,每天会计算上个月的订单和当月的订单和。一月的订单周期是一个有1日12点到下个月的1日12点。

如前当3月31日,上个月的周期是2月1日12点到3月1日12点;本月的周期是3月1点12到当前时间点。

逻辑在处理上个月的订单时用了 AddDate

lastMonth := time.AddDate(0, -1, 0).Format("200601")

问题就出现在这里。 当前时间是3月31时,time.AddDate(0, -1, 0) 之后,是 20240302 ,还是3月份,并不符合预期。

如下代码:

package main

import (
	"fmt"
	"time"
)

func main() {

	today := time.Date(2024, 2, 29, 0, 0, 0, 0, time.Local)
	nextDay := today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 3, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 4, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 5, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 6, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 7, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 8, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 9, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 10, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 11, 30, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

	today = time.Date(2024, 12, 31, 0, 0, 0, 0, time.Local)
	nextDay = today.AddDate(0, -1, 0)
	fmt.Printf("today :%v nextDay :%+v \n", today.Format("20060102"), nextDay.Format("20060102"))

}

输出:

today :20240229 nextDay :20240129
today :20240331 nextDay :20240302
today :20240430 nextDay :20240330
today :20240531 nextDay :20240501
today :20240630 nextDay :20240530
today :20240731 nextDay :20240701
today :20240831 nextDay :20240731
today :20240930 nextDay :20240830
today :20241031 nextDay :20241001
today :20241130 nextDay :20241030
today :20241231 nextDay :20241201

其中,如 20240331、20240531、20240731、20241031 这一些时算的上月时间就出错,它依然是本月的时间。

解决这个问题最简单,最快的方式是引用库 https://github.com/Andrew-M-C/go.timeconv

package main

import (
	"fmt"
	"time"
	"github.com/Andrew-M-C/go.timeconv"
)

func main() {
	t := time.Date(2019, 1, 31, 0, 0, 0, 0, time.UTC)
	nt := t.AddDate(0, 1, 0)	// Add one month
	fmt.Printf("%v\n", nt)		// 2019-03-03 00:00:00 +0000 UTC, not expected

	nt = timeconv.AddDate(t, 0, 1, 0)
	fmt.Printf("%v\n", nt)		// 2019-02-28 00:00:00 +0000 UTC
}

1、令人困惑的 Go time.AddDate https://learnku.com/articles/71760

2、Go time 包中的 AddDate 的逻辑避坑指南 https://cloud.tencent.com/developer/article/1803695


上一篇     下一篇