package main

import (
	"log"
	"time"
)

func main() {
	t1 := time.Date(2022, 3, 31, 0, 0, 0, 0, time.Local)
	log.Println(t1.Format("2006-01-02 15:04:05:000"))
	t11 := t1.AddDate(0, -1, 0)
	log.Println(t11.Format("2006-01-02 15:04:05:000"))
	log.Println("---")
	t2 := time.Date(2022, 4, 1, 0, 0, 0, 0, time.Local)
	log.Println(t2.Format("2006-01-02 15:04:05:000"))
	t21 := t2.AddDate(0, -1, 0)
	log.Println(t21.Format("2006-01-02 15:04:05:000"))
}

输出

2022-03-31 00:00:00:000
2022-03-03 00:00:00:000
---
2022-04-01 00:00:00:000
2022-03-01 00:00:00:000

避坑
https://www.vicw.com/groups/code_monkey/topics/341

// AddDate 时间增减
// 类似于ruby中的时间增减,和 time.AddDate 不同
// 如:
// loc, _ := time.LoadLocation("Asia/Shanghai")
// t := time.Date(2010, 3, 31, 12, 0, 0, 0, loc)
// utils.AddDate(t, 0, 1)
// => 2010-04-30 12:00:00 +0800 CST
// 不会因为4月没有31号,而变成5月1号
func AddDate2(t time.Time, years int, months int) time.Time {
	year, month, day := t.Date()
	hour, min, sec := t.Clock()

	// firstDayOfMonthAfterAddDate: years 年,months 月后的 那个月份的1号
	firstDayOfMonthAfterAddDate := time.Date(year+years, month+time.Month(months), 1,
		hour, min, sec, t.Nanosecond(), t.Location())

	// firstDayOfMonthAfterAddDate 月份的最后一天
	lastDay := firstDayOfMonthAfterAddDate.AddDate(0, 1, 0).Add(-time.Nanosecond).Day()

	// 如果 t 的天 > lastDay,则设置为lastDay
	// 如:t 为 2020-03-31 12:00:00 +0800,增加1个月,为4月31号
	// 但是4月没有31号,则设置为4月最后一天lastDay(30号)
	if day > lastDay {
		day = lastDay
	}

	return time.Date(year+years, month+time.Month(months), day,
		hour, min, sec, t.Nanosecond(), t.Location())
}