diff --git a/difference.go b/difference.go index 2d5cec2..25aed97 100755 --- a/difference.go +++ b/difference.go @@ -144,7 +144,7 @@ func (c Carbon) DiffInSeconds(carbon ...Carbon) int64 { if len(carbon) > 0 { end = carbon[len(carbon)-1] } - return end.ToTimestamp() - c.ToTimestamp() + return end.Timestamp() - c.Timestamp() } // DiffInSecondsWithAbs gets the difference in seconds with absolute value. @@ -157,6 +157,34 @@ func (c Carbon) DiffInSecondsWithAbs(carbon ...Carbon) int64 { return getAbsValue(c.DiffInSeconds(end)) } +// DiffInString gets the difference in string, i18n is supported. +// 相差字符串,支持i18n +func (c Carbon) DiffInString(carbon ...Carbon) string { + end := c.Now() + if len(carbon) > 0 { + end = carbon[len(carbon)-1] + } + if c.Error != nil || end.Error != nil { + return "" + } + unit, value := c.diff(end) + return c.lang.translate(unit, value) +} + +// DiffInString gets the difference in string with absolute value, i18n is supported. +// 相差字符串,支持i18n +func (c Carbon) DiffInStringWithAbs(carbon ...Carbon) string { + end := c.Now() + if len(carbon) > 0 { + end = carbon[len(carbon)-1] + } + if c.Error != nil || end.Error != nil { + return "" + } + unit, value := c.diff(end) + return c.lang.translate(unit, getAbsValue(value)) +} + // DiffForHumans gets the difference in a human readable format, i18n is supported. // 获取对人类友好的可读格式时间差,支持i18n func (c Carbon) DiffForHumans(carbon ...Carbon) string { @@ -164,40 +192,14 @@ func (c Carbon) DiffForHumans(carbon ...Carbon) string { if len(carbon) > 0 { end = carbon[len(carbon)-1] } - unit, diff := "", int64(0) - switch true { - case c.DiffInYearsWithAbs(end) > 0: - unit = "year" - diff = c.DiffInYearsWithAbs(end) - break - case c.DiffInMonthsWithAbs(end) > 0: - unit = "month" - diff = c.DiffInMonthsWithAbs(end) - break - case c.DiffInWeeksWithAbs(end) > 0: - unit = "week" - diff = c.DiffInWeeksWithAbs(end) - break - case c.DiffInDaysWithAbs(end) > 0: - unit = "day" - diff = c.DiffInDaysWithAbs(end) - break - case c.DiffInHoursWithAbs(end) > 0: - unit = "hour" - diff = c.DiffInHoursWithAbs(end) - break - case c.DiffInMinutesWithAbs(end) > 0: - unit = "minute" - diff = c.DiffInMinutesWithAbs(end) - case c.DiffInSecondsWithAbs(end) > 0: - unit = "second" - diff = c.DiffInSecondsWithAbs(end) - case c.DiffInSecondsWithAbs(end) == 0: - unit = "now" - diff = 0 - return c.lang.translate(unit, diff) + if c.Error != nil || end.Error != nil { + return "" + } + unit, value := c.diff(end) + translation := c.lang.translate(unit, getAbsValue(value)) + if unit == "now" { + return translation } - translation := c.lang.translate(unit, diff) if c.Lt(end) && len(carbon) == 0 { return strings.Replace(c.lang.resources["ago"], "%s", translation, 1) } @@ -209,3 +211,40 @@ func (c Carbon) DiffForHumans(carbon ...Carbon) string { } return strings.Replace(c.lang.resources["after"], "%s", translation, 1) } + +// diff gets the difference for unit and value. +// 获取相差单位和差值 +func (c Carbon) diff(end Carbon) (unit string, value int64) { + switch true { + case c.DiffInYearsWithAbs(end) > 0: + unit = "year" + value = c.DiffInYears(end) + break + case c.DiffInMonthsWithAbs(end) > 0: + unit = "month" + value = c.DiffInMonths(end) + break + case c.DiffInWeeksWithAbs(end) > 0: + unit = "week" + value = c.DiffInWeeks(end) + break + case c.DiffInDaysWithAbs(end) > 0: + unit = "day" + value = c.DiffInDays(end) + break + case c.DiffInHoursWithAbs(end) > 0: + unit = "hour" + value = c.DiffInHours(end) + break + case c.DiffInMinutesWithAbs(end) > 0: + unit = "minute" + value = c.DiffInMinutes(end) + case c.DiffInSecondsWithAbs(end) > 0: + unit = "second" + value = c.DiffInSeconds(end) + case c.DiffInSecondsWithAbs(end) == 0: + unit = "now" + value = 0 + } + return +} diff --git a/difference_test.go b/difference_test.go index 200493b..4f1766b 100755 --- a/difference_test.go +++ b/difference_test.go @@ -354,6 +354,127 @@ func TestCarbon_DiffInSecondsWithAbs(t *testing.T) { } } +func TestCarbon_DiffInString(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + input Carbon // 输入值 + expected string // 期望值 + }{ + {Now(), "just now"}, + + {Now().AddYearsNoOverflow(1), "-1 year"}, + {Now().SubYearsNoOverflow(1), "1 year"}, + {Now().AddYearsNoOverflow(10), "-10 years"}, + {Now().SubYearsNoOverflow(10), "10 years"}, + + {Now().AddMonthsNoOverflow(1), "-1 month"}, + {Now().SubMonthsNoOverflow(1), "1 month"}, + {Now().AddMonthsNoOverflow(10), "-10 months"}, + {Now().SubMonthsNoOverflow(10), "10 months"}, + + {Now().AddDays(1), "-1 day"}, + {Now().SubDays(1), "1 day"}, + {Now().AddDays(10), "-1 week"}, + {Now().SubDays(10), "1 week"}, + + {Now().AddHours(1), "-1 hour"}, + {Now().SubHours(1), "1 hour"}, + {Now().AddHours(10), "-10 hours"}, + {Now().SubHours(10), "10 hours"}, + + {Now().AddMinutes(1), "-1 minute"}, + {Now().SubMinutes(1), "1 minute"}, + {Now().AddMinutes(10), "-10 minutes"}, + {Now().SubMinutes(10), "10 minutes"}, + + {Now().AddSeconds(1), "-1 second"}, + {Now().SubSeconds(1), "1 second"}, + {Now().AddSeconds(10), "-10 seconds"}, + {Now().SubSeconds(10), "10 seconds"}, + } + + for index, test := range tests { + c := test.input + assert.Nil(c.Error) + assert.Equal(test.expected, c.DiffInString(), "Current test index is "+strconv.Itoa(index)) + } + for index, test := range tests { + c := test.input + assert.Nil(c.Error) + assert.Equal(test.expected, c.DiffInString(Now()), "Current test index is "+strconv.Itoa(index)) + } +} + +func TestLangError_DiffInString(t *testing.T) { + lang := NewLanguage() + lang.SetLocale("xxx") + c := Now().SetLanguage(lang).AddMonths(1) + assert.NotNil(t, c.Error, "It should catch an exception in DiffInString()") + assert.Equal(t, "", c.DiffInString()) +} + +func TestCarbon_DiffInStringWithAbs(t *testing.T) { + assert := assert.New(t) + + tests := []struct { + input Carbon // 输入值 + expected string // 期望值 + }{ + {Now(), "just now"}, + + {Now().AddYearsNoOverflow(1), "1 year"}, + {Now().SubYearsNoOverflow(1), "1 year"}, + {Now().AddYearsNoOverflow(10), "10 years"}, + {Now().SubYearsNoOverflow(10), "10 years"}, + + {Now().AddMonthsNoOverflow(1), "1 month"}, + {Now().SubMonthsNoOverflow(1), "1 month"}, + {Now().AddMonthsNoOverflow(10), "10 months"}, + {Now().SubMonthsNoOverflow(10), "10 months"}, + + {Now().AddDays(1), "1 day"}, + {Now().SubDays(1), "1 day"}, + {Now().AddDays(10), "1 week"}, + {Now().SubDays(10), "1 week"}, + + {Now().AddHours(1), "1 hour"}, + {Now().SubHours(1), "1 hour"}, + {Now().AddHours(10), "10 hours"}, + {Now().SubHours(10), "10 hours"}, + + {Now().AddMinutes(1), "1 minute"}, + {Now().SubMinutes(1), "1 minute"}, + {Now().AddMinutes(10), "10 minutes"}, + {Now().SubMinutes(10), "10 minutes"}, + + {Now().AddSeconds(1), "1 second"}, + {Now().SubSeconds(1), "1 second"}, + {Now().AddSeconds(10), "10 seconds"}, + {Now().SubSeconds(10), "10 seconds"}, + } + + for index, test := range tests { + c := test.input + assert.Nil(c.Error) + assert.Equal(test.expected, c.DiffInStringWithAbs(), "Current test index is "+strconv.Itoa(index)) + } + + for index, test := range tests { + c := test.input + assert.Nil(c.Error) + assert.Equal(test.expected, c.DiffInStringWithAbs(Now()), "Current test index is "+strconv.Itoa(index)) + } +} + +func TestLangError_DiffInStringWithAbs(t *testing.T) { + lang := NewLanguage() + lang.SetLocale("xxx") + c := Now().SetLanguage(lang).AddMonths(1) + assert.NotNil(t, c.Error, "It should catch an exception in DiffInStringWithAbs()") + assert.Equal(t, "", c.DiffInStringWithAbs()) +} + func TestCarbon_DiffForHumans(t *testing.T) { assert := assert.New(t) @@ -400,3 +521,11 @@ func TestCarbon_DiffForHumans(t *testing.T) { assert.Equal(test.expected, c.DiffForHumans(), "Current test index is "+strconv.Itoa(index)) } } + +func TestLangError_DiffForHumans(t *testing.T) { + lang := NewLanguage() + lang.SetLocale("xxx") + c := Now().SetLanguage(lang).AddMonths(1) + assert.NotNil(t, c.Error, "It should catch an exception in DiffForHumans()") + assert.Equal(t, "", c.DiffForHumans()) +}