修复 DiffInMonths 计算错误

This commit is contained in:
gouguoyin 2024-11-24 23:48:04 +08:00
parent 6da137e5d7
commit 222cd8e117
3 changed files with 117 additions and 24 deletions

View File

@ -40,20 +40,15 @@ func (c Carbon) DiffAbsInYears(carbon ...Carbon) int64 {
// DiffInMonths gets the difference in months.
// 相差多少月
func (c Carbon) DiffInMonths(carbon ...Carbon) int64 {
start := c
end := c.Now()
if c.IsSetTestNow() {
if start.IsSetTestNow() {
end = CreateFromTimestampNano(c.testNow, c.Location())
}
if len(carbon) > 0 {
end = carbon[0]
}
if c.DiffAbsInDays(end) < 28 {
return 0
}
startYear, startMonth, _ := c.Date()
endYear, endMonth, _ := end.Date()
diffYear, diffMonth := endYear-startYear, endMonth-startMonth
return int64(diffYear*MonthsPerYear + diffMonth)
return getDiffInMonths(start, end)
}
// DiffAbsInMonths gets the difference in months with absolute value.
@ -275,3 +270,29 @@ func (c Carbon) diff(end Carbon) (unit string, value int64) {
}
return
}
func getDiffInMonths(c1 Carbon, c2 Carbon) int64 {
if c1.Month() == c2.Month() && c1.Year() == c2.Year() {
return 0
}
diffInDays := c1.DiffInDays(c2)
start, end := c2, c1
reg := -int64(1)
if diffInDays > 0 {
start, end = c1, c2
reg = int64(1)
}
months := getMonthsFromMonthToMonth(start, end, 0)
return months * reg
}
func getMonthsFromMonthToMonth(c1 Carbon, c2 Carbon, months int64) int64 {
date := c1.AddDays(c1.DaysInMonth())
diffInDays := date.DiffInDays(c2)
diffInSeconds := date.DiffInSeconds(c2)
if diffInDays < 0 || diffInDays == 0 && diffInSeconds < 0 {
return months
}
months += 1
return getMonthsFromMonthToMonth(date, c2, months)
}

View File

@ -127,7 +127,7 @@ func TestCarbon_DiffInMonths(t *testing.T) {
name: "case4",
carbon1: Parse("2020-08-05 13:14:15"),
carbon2: Parse("2018-08-28 13:14:59"),
want: -24,
want: -23,
},
}
@ -167,7 +167,7 @@ func TestCarbon_DiffAbsInMonths(t *testing.T) {
name: "case4",
carbon1: Parse("2020-08-05 13:14:15"),
carbon2: Parse("2018-08-28 13:14:59"),
want: 24,
want: 23,
},
}
@ -872,13 +872,13 @@ func TestCarbon_DiffInDuration(t *testing.T) {
name: "case6",
carbon1: now.AddMonthsNoOverflow(1),
carbon2: now,
want: "-744h0m0s",
want: "-720h0m0s",
},
{
name: "case7",
carbon1: now.SubMonthsNoOverflow(1),
carbon2: now,
want: "720h0m0s",
want: "744h0m0s",
},
{
@ -944,13 +944,13 @@ func TestCarbon_DiffAbsInDuration(t *testing.T) {
name: "case6",
carbon1: now.AddMonthsNoOverflow(1),
carbon2: now,
want: "744h0m0s",
want: "720h0m0s",
},
{
name: "case7",
carbon1: now.SubMonthsNoOverflow(1),
carbon2: now,
want: "720h0m0s",
want: "744h0m0s",
},
{
@ -1047,3 +1047,75 @@ func TestCarbon_DiffForHumans(t *testing.T) {
}
}
// https://github.com/golang-module/carbon/issues/255
func TestCarbon_Issue255(t *testing.T) {
tests := []struct {
name string
start Carbon
end Carbon
want int64
}{
{
name: "case1",
start: Parse("2024-10-11"),
end: Parse("2024-11-10"),
want: 0,
},
{
name: "case2",
start: Parse("2024-11-10"),
end: Parse("2024-10-11"),
want: 0,
},
{
name: "case3",
start: Parse("2024-10-11"),
end: Parse("2024-11-11"),
want: 1,
},
{
name: "case4",
start: Parse("2024-11-11"),
end: Parse("2024-10-11"),
want: -1,
},
{
name: "case5",
start: Parse("2024-10-11 23:59:00"),
end: Parse("2024-11-11 00:00:00"),
want: 0,
},
{
name: "case6",
start: Parse("2024-11-11 00:00:00"),
end: Parse("2024-10-11 23:59:00"),
want: 0,
},
{
name: "case7",
start: Parse("2024-10-11 00:00:00"),
end: Parse("2024-11-11 23:59:59"),
want: 1,
},
{
name: "case8",
start: Parse("2024-11-11 23:59:59"),
end: Parse("2024-10-11 00:00:00"),
want: -1,
},
{
name: "case9",
start: Parse("2020-08-05 13:14:15"),
end: Parse("2018-08-28 13:14:59"),
want: -23,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
assert.Equalf(t, tt.want, tt.start.DiffInMonths(tt.end), "DiffInMonths()")
})
}
}

View File

@ -147,6 +147,16 @@ func TestCarbon_ParseByLayout(t *testing.T) {
}
}
func TestError_ParseByLayout(t *testing.T) {
assert.NotNil(t, ParseByLayout("2020-08-05", "2006-03-04", "xxx").Error, "It should catch an exception in ParseByLayout")
assert.NotNil(t, ParseByLayout("xxx", "2006-03-04", PRC).Error, "It should catch an exception in ParseByLayout")
}
func TestError_ParseByFormat(t *testing.T) {
assert.NotNil(t, ParseByFormat("2020-08-05", "Y-m-d", "xxx").Error, "It should catch an exception in ParseByFormat()")
assert.NotNil(t, ParseByFormat("xxx", "Y-m-d", PRC).Error, "It should catch an exception in ParseByFormat")
}
// https://github.com/golang-module/carbon/issues/202
func TestCarbon_Issue202(t *testing.T) {
tests := []struct {
@ -183,16 +193,6 @@ func TestCarbon_Issue202(t *testing.T) {
}
}
func TestError_ParseByLayout(t *testing.T) {
assert.NotNil(t, ParseByLayout("2020-08-05", "2006-03-04", "xxx").Error, "It should catch an exception in ParseByLayout")
assert.NotNil(t, ParseByLayout("xxx", "2006-03-04", PRC).Error, "It should catch an exception in ParseByLayout")
}
func TestError_ParseByFormat(t *testing.T) {
assert.NotNil(t, ParseByFormat("2020-08-05", "Y-m-d", "xxx").Error, "It should catch an exception in ParseByFormat()")
assert.NotNil(t, ParseByFormat("xxx", "Y-m-d", PRC).Error, "It should catch an exception in ParseByFormat")
}
// https://github.com/golang-module/carbon/issues/206
func TestCarbon_Issue206(t *testing.T) {
tests := []struct {