Go语言中正确获取上月日期的方法(解决AddDate异常)
Go语言中正确获取上月日期的方法
当使用time.AddDate()处理月末日期时,会因为日期规范化逻辑导致结果不符合预期。比如你提到的例子:
mayEndDate := time.Date(2021, 5, 31, 12, 00, 00, 00, time.UTC) finalDate := mayEndDate.AddDate(0, -1, 0) // 修正原代码变量名笔误
运行后finalDate得到2021-05-01 12:00:00 +0000 UTC,而非预期的4月日期。原因是AddDate会自动规范化不存在的日期:5月31日减1个月会试图构造4月31日,但4月只有30天,因此被调整为5月1日。
以下是两种可靠的解决方案:
方法一:通过当月第一天倒推上月最后一天
先获取当前日期所在月份的第一天,再减去1天,就能得到上月的最后一天,同时可以保留原日期的时分秒信息:
mayEndDate := time.Date(2021, 5, 31, 12, 0, 0, 0, time.UTC) // 获取当月第一天(时分秒设为0) firstDayOfCurrMonth := time.Date(mayEndDate.Year(), mayEndDate.Month(), 1, 0, 0, 0, 0, mayEndDate.Location()) // 减1天得到上月最后一天,并保留原日期的时分秒 lastDayOfPrevMonth := time.Date( firstDayOfCurrMonth.AddDate(0, 0, -1).Year(), firstDayOfCurrMonth.AddDate(0, 0, -1).Month(), firstDayOfCurrMonth.AddDate(0, 0, -1).Day(), mayEndDate.Hour(), mayEndDate.Minute(), mayEndDate.Second(), mayEndDate.Nanosecond(), mayEndDate.Location(), ) // 输出:2021-04-30 12:00:00 +0000 UTC
方法二:构造上月日期后校验修正
先尝试构造上月的相同日期,如果构造后的月份不是预期的上月,则说明上月没有该日期,此时取上月的最后一天:
func getPrevMonthDate(t time.Time) time.Time { year, month, day := t.Date() loc := t.Location() // 尝试构造上月的相同日期 prevDate := time.Date(year, month-1, day, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), loc) // 校验是否为上月,若不是则取上月最后一天 if prevDate.Month() != month-1 { prevDate = time.Date(year, month, 1, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), loc).AddDate(0, 0, -1) } return prevDate } // 使用示例 mayEndDate := time.Date(2021, 5, 31, 12, 0, 0, 0, time.UTC) finalDate := getPrevMonthDate(mayEndDate) // 输出:2021-04-30 12:00:00 +0000 UTC
这两种方法都能避免AddDate的规范化问题,准确得到上月的对应日期(月末日期会自动适配上月最后一天)。
内容的提问来源于stack exchange,提问作者Ayush
相关产品推荐
相关产品推荐

