mirror of
https://github.com/duke-git/lancet.git
synced 2026-02-04 12:52:28 +08:00
feat: add AddDaySafe, AddMonthSafe, AddYearSafe
This commit is contained in:
@@ -100,6 +100,61 @@ func AddYear(t time.Time, year int64) time.Time {
|
||||
return t.AddDate(int(year), 0, 0)
|
||||
}
|
||||
|
||||
// AddDaySafe add or sub days to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
// Play: todo
|
||||
func AddDaySafe(t time.Time, days int) time.Time {
|
||||
t = t.AddDate(0, 0, days)
|
||||
year, month, day := t.Date()
|
||||
|
||||
lastDayOfMonth := time.Date(year, month+1, 0, 0, 0, 0, 0, t.Location()).Day()
|
||||
|
||||
if day > lastDayOfMonth {
|
||||
t = time.Date(year, month, lastDayOfMonth, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
|
||||
}
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// AddMonthSafe add or sub months to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
// Play: todo
|
||||
func AddMonthSafe(t time.Time, months int) time.Time {
|
||||
year := t.Year()
|
||||
month := int(t.Month()) + months
|
||||
|
||||
for month > 12 {
|
||||
month -= 12
|
||||
year++
|
||||
}
|
||||
for month < 1 {
|
||||
month += 12
|
||||
year--
|
||||
}
|
||||
|
||||
daysInMonth := time.Date(year, time.Month(month+1), 0, 0, 0, 0, 0, time.UTC).Day()
|
||||
|
||||
day := t.Day()
|
||||
if day > daysInMonth {
|
||||
day = daysInMonth
|
||||
}
|
||||
|
||||
return time.Date(year, time.Month(month), day, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
|
||||
}
|
||||
|
||||
// AddYearSafe add or sub years to the time and ensure that the returned date does not exceed the valid date of the target year and month.
|
||||
// Play: todo
|
||||
func AddYearSafe(t time.Time, years int) time.Time {
|
||||
year, month, day := t.Date()
|
||||
year += years
|
||||
|
||||
if month == time.February && day == 29 {
|
||||
if !IsLeapYear(year) {
|
||||
day = 28
|
||||
}
|
||||
}
|
||||
|
||||
return time.Date(year, month, day, t.Hour(), t.Minute(), t.Second(), t.Nanosecond(), t.Location())
|
||||
}
|
||||
|
||||
// GetNowDate return format yyyy-mm-dd of current date.
|
||||
// Play: https://go.dev/play/p/PvfkPpcpBBf
|
||||
func GetNowDate() string {
|
||||
|
||||
@@ -90,6 +90,60 @@ func ExampleAddYear() {
|
||||
// 2019-01-01
|
||||
}
|
||||
|
||||
func ExampleAddDaySafe() {
|
||||
leapYearDate1, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result1 := AddDaySafe(leapYearDate1, 1)
|
||||
|
||||
leapYearDate2, _ := time.Parse("2006-01-02", "2024-03-01")
|
||||
result2 := AddDaySafe(leapYearDate2, -1)
|
||||
|
||||
nonLeapYearDate1, _ := time.Parse("2006-01-02", "2025-02-28")
|
||||
result3 := AddDaySafe(nonLeapYearDate1, 1)
|
||||
|
||||
nonLeaYearDate2, _ := time.Parse("2006-01-02", "2025-03-01")
|
||||
result4 := AddDaySafe(nonLeaYearDate2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
fmt.Println(result3.Format("2006-01-02"))
|
||||
fmt.Println(result4.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2024-03-01
|
||||
// 2024-02-29
|
||||
// 2025-03-01
|
||||
// 2025-02-28
|
||||
}
|
||||
|
||||
func ExampleAddMonthSafe() {
|
||||
date1, _ := time.Parse("2006-01-02", "2025-01-31")
|
||||
result1 := AddMonthSafe(date1, 1)
|
||||
|
||||
date2, _ := time.Parse("2006-01-02", "2024-02-29")
|
||||
result2 := AddMonthSafe(date2, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2025-02-28
|
||||
// 2024-01-29
|
||||
}
|
||||
|
||||
func ExampleAddYearSafe() {
|
||||
date, _ := time.Parse("2006-01-02", "2020-02-29")
|
||||
|
||||
result1 := AddYearSafe(date, 1)
|
||||
result2 := AddYearSafe(date, -1)
|
||||
|
||||
fmt.Println(result1.Format("2006-01-02"))
|
||||
fmt.Println(result2.Format("2006-01-02"))
|
||||
|
||||
// Output:
|
||||
// 2021-02-28
|
||||
// 2019-02-28
|
||||
}
|
||||
|
||||
func ExampleGetNowDate() {
|
||||
result := GetNowDate()
|
||||
|
||||
|
||||
@@ -309,6 +309,129 @@ func TestAddMonth(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestAddDaySafe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddDaySafe")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
days int
|
||||
expected string
|
||||
}{
|
||||
{"2025-01-31", 10, "2025-02-10"},
|
||||
{"2025-01-01", 30, "2025-01-31"},
|
||||
{"2025-01-31", 1, "2025-02-01"},
|
||||
{"2025-02-28", 1, "2025-03-01"},
|
||||
{"2024-02-29", 1, "2024-03-01"},
|
||||
{"2024-02-29", 365, "2025-02-28"},
|
||||
|
||||
{"2025-01-31", -10, "2025-01-21"},
|
||||
{"2025-01-01", -30, "2024-12-02"},
|
||||
{"2025-02-01", -1, "2025-01-31"},
|
||||
{"2025-03-01", -1, "2025-02-28"},
|
||||
{"2024-03-01", -1, "2024-02-29"},
|
||||
|
||||
{"2025-01-31", -31, "2024-12-31"},
|
||||
{"2025-12-31", 1, "2026-01-01"},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddDaySafe(date, tt.days)
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestAddMonthSafe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddMonthSafe")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
months int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2025-01-31",
|
||||
months: 1,
|
||||
expected: "2025-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2025-01-31",
|
||||
months: -1,
|
||||
expected: "2024-12-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2025-12-31",
|
||||
months: 1,
|
||||
expected: "2026-01-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2025-01-31",
|
||||
months: -1,
|
||||
expected: "2024-12-31",
|
||||
},
|
||||
{
|
||||
inputDate: "2024-02-29",
|
||||
months: 1,
|
||||
expected: "2024-03-29",
|
||||
},
|
||||
{
|
||||
inputDate: "2024-02-29",
|
||||
months: -1,
|
||||
expected: "2024-01-29",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddMonthSafe(date, tt.months)
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func TestAddYearSafe(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert := internal.NewAssert(t, "TestAddYearSafe")
|
||||
|
||||
tests := []struct {
|
||||
inputDate string
|
||||
years int
|
||||
expected string
|
||||
}{
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: 1,
|
||||
expected: "2021-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: 2,
|
||||
expected: "2022-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: -1,
|
||||
expected: "2019-02-28",
|
||||
},
|
||||
{
|
||||
inputDate: "2020-02-29",
|
||||
years: -2,
|
||||
expected: "2018-02-28",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
date, _ := time.Parse("2006-01-02", tt.inputDate)
|
||||
result := AddYearSafe(date, tt.years)
|
||||
assert.Equal(tt.expected, result.Format("2006-01-02"))
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetNowDate(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user