Skip to content

Commit

Permalink
[RFC] Fix month calculation between dates (#77)
Browse files Browse the repository at this point in the history
* Fix month calculation between dates

* Remove unused function
  • Loading branch information
rntdrts authored Apr 17, 2022
1 parent f18c311 commit 2bcf706
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 38 deletions.
58 changes: 20 additions & 38 deletions carbon.go
Original file line number Diff line number Diff line change
Expand Up @@ -1195,50 +1195,40 @@ func (c *Carbon) DiffInMonths(carb *Carbon, abs bool) int64 {
return calculateDiffInMonths(cAux, carbAux, abs)
}

func calculateDiffInMonths(c, carb *Carbon, abs bool) int64 {
func calculateDiffInMonths(c *Carbon, carb *Carbon, abs bool) int64 {
if c.Month() == carb.Month() && c.Year() == carb.Year() {
return 0
}

if c.Month() != carb.Month() && c.Year() == carb.Year() {
diffInMonths := int64(carb.Month() - c.Month())
remainingTime, totalHours := calculateDiffInTimeAndHours(c, carb)
diffInDays := c.DiffInDays(carb, false)

if remainingTime < totalHours {
return 0
}

return absValue(abs, diffInMonths)
}
end := c.Copy()
start := carb.Copy()
reg := -int64(1)

m := monthsPerYear - c.Month() + carb.Month() - 1
if c.Year() < carb.Year() && c.hasRemainingHours(carb) {
m = m + 1
if diffInDays > 0 {
end = carb.Copy()
start = c.Copy()
reg = int64(1)
}

if c.Year() > carb.Year() {
m = monthsPerYear - carb.Month() + c.Month() - 1
months := calculateFromMonthToMonth(start, end, 0)

if carb.hasRemainingHours(c) {
m = m + 1
}
}
return absValue(abs, int64(months*reg))
}

diffYr := c.Year() - carb.Year()
if math.Abs(float64(diffYr)) > 1 {
dateWithoutMonths := c.AddMonths(int(m))
diff := dateWithoutMonths.DiffInYears(carb, abs)*monthsPerYear + int64(m)
func calculateFromMonthToMonth(start *Carbon, end *Carbon, months int64) int64 {
date := start.AddDays(start.DaysInMonth())
diffInDays := date.DiffInDays(end, false)
diffInSeconds := date.DiffInSeconds(end, false)

return absValue(abs, diff)
if diffInDays < 0 || diffInDays == 0 && diffInSeconds < 0 {
return months
}

diff := int64(m)
months += 1

if c.GreaterThan(carb) {
diff = -diff
}

return absValue(abs, diff)
return calculateFromMonthToMonth(date, end, months)
}

func (c *Carbon) hasRemainingHours(carb *Carbon) bool {
Expand Down Expand Up @@ -1838,14 +1828,6 @@ func (c *Carbon) SetLocale(l string) error {
return nil
}

func calculateDiffInTimeAndHours(c, carb *Carbon) (int, int) {
if carb.Timestamp() < c.Timestamp() {
return int(c.DiffInHours(carb, true)), carb.DaysInMonth() * hoursPerDay
}

return int(carb.DiffInHours(c, true)), c.DaysInMonth() * hoursPerDay
}

/* TODO
// String Formatting
Expand Down
15 changes: 15 additions & 0 deletions carbon_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1935,6 +1935,14 @@ func TestDiffInMonthsTimeZone(t *testing.T) {
t1, _ := Create(2016, time.August, 18, 10, 0, 0, 0, "UTC")
t2, _ := Create(2016, time.January, 18, 12, 0, 0, 0, "Europe/Madrid")

// On January the diff from UTC and Europe/Madrid is only one hour
assert.EqualValues(t, 6, t1.DiffInMonths(t2, true))
}

func TestDiffInMonthsTimeZoneWithSameTimeDiff(t *testing.T) {
t1, _ := Create(2016, time.August, 18, 10, 0, 0, 0, "UTC")
t2, _ := Create(2016, time.January, 18, 11, 0, 0, 0, "Europe/Madrid")

assert.EqualValues(t, 7, t1.DiffInMonths(t2, true))
}

Expand Down Expand Up @@ -1966,6 +1974,13 @@ func TestDiffInMonthsMoreThanTwoYears(t *testing.T) {
assert.EqualValues(t, 82, t1.DiffInMonths(t2, true))
}

func TestDiffInMonthsTwoOverlapingYears(t *testing.T) {
t1, _ := Create(2019, 07, 1, 0, 0, 0, 0, time.UTC.String())
t2, _ := Create(2021, 07, 24, 0, 0, 0, 0, time.UTC.String())

assert.EqualValues(t, 24, t1.DiffInMonths(t2, true))
}

func TestDiffInMonthsOneDayDifference(t *testing.T) {
t1, _ := Create(2016, time.September, 1, 10, 0, 0, 0, "UTC")
t2, _ := Create(2016, time.August, 31, 10, 0, 0, 0, "UTC")
Expand Down

0 comments on commit 2bcf706

Please sign in to comment.