Allow custom defined relative time format.
Add a new func to allow user to customize units and output format
for relative time.
diff --git a/times.go b/times.go
index 49906b3..9d48eea 100644
--- a/times.go
+++ b/times.go
@@ -25,28 +25,49 @@
return RelTime(then, time.Now(), "ago", "from now")
}
-var magnitudes = []struct {
+// Seconds represents the elapsed time between two instants as an int64 second count.
+type Seconds int64
+
+// Magnitude stores one magnitude and the output format for this magnitude of relative time.
+type Magnitude struct {
d int64
format string
divby int64
-}{
- {1, "now", 1},
- {2, "1 second %s", 1},
- {Minute, "%d seconds %s", 1},
- {2 * Minute, "1 minute %s", 1},
- {Hour, "%d minutes %s", Minute},
- {2 * Hour, "1 hour %s", 1},
- {Day, "%d hours %s", Hour},
- {2 * Day, "1 day %s", 1},
- {Week, "%d days %s", Day},
- {2 * Week, "1 week %s", 1},
- {Month, "%d weeks %s", Week},
- {2 * Month, "1 month %s", 1},
- {Year, "%d months %s", Month},
- {18 * Month, "1 year %s", 1},
- {2 * Year, "2 years %s", 1},
- {LongTime, "%d years %s", Year},
- {math.MaxInt64, "a long while %s", 1},
+}
+
+// NewMagnitude returns a Magnitude object.
+//
+// d is the max number value of relative time for this magnitude.
+// divby is the divisor to turn input number value into expected unit.
+// format is the expected output format string.
+//
+// Also refer to RelTimeMagnitudes for examples.
+func NewMagnitude(d Seconds, format string, divby Seconds) Magnitude {
+ return Magnitude{
+ d: int64(d),
+ format: format,
+ divby: int64(divby),
+ }
+}
+
+var defaultMagnitudes = []Magnitude{
+ NewMagnitude(1, "now", 1),
+ NewMagnitude(2, "1 second %s", 1),
+ NewMagnitude(Minute, "%d seconds %s", 1),
+ NewMagnitude(2*Minute, "1 minute %s", 1),
+ NewMagnitude(Hour, "%d minutes %s", Minute),
+ NewMagnitude(2*Hour, "1 hour %s", 1),
+ NewMagnitude(Day, "%d hours %s", Hour),
+ NewMagnitude(2*Day, "1 day %s", 1),
+ NewMagnitude(Week, "%d days %s", Day),
+ NewMagnitude(2*Week, "1 week %s", 1),
+ NewMagnitude(Month, "%d weeks %s", Week),
+ NewMagnitude(2*Month, "1 month %s", 1),
+ NewMagnitude(Year, "%d months %s", Month),
+ NewMagnitude(18*Month, "1 year %s", 1),
+ NewMagnitude(2*Year, "2 years %s", 1),
+ NewMagnitude(LongTime, "%d years %s", Year),
+ NewMagnitude(math.MaxInt64, "a long while %s", 1),
}
// RelTime formats a time into a relative string.
@@ -57,6 +78,30 @@
//
// RelTime(timeInPast, timeInFuture, "earlier", "later") -> "3 weeks earlier"
func RelTime(a, b time.Time, albl, blbl string) string {
+ return RelTimeMagnitudes(a, b, albl, blbl, defaultMagnitudes)
+}
+
+// RelTimeMagnitudes accepts a magnitudes parameter to allow custom defined units and output format.
+//
+// example:
+// magitudes:
+// {
+// NewMagnitude(1, "now", 1),
+// NewMagnitude(60, "%d seconds %s", 1),
+// NewMagnitude(120,"a minute %s", 1),
+// NewMagnitude(360, "%d minutes %s", 60),
+// }
+// albl: earlier
+// blbl: later
+//
+// b - a output
+// -130 2 minutes later
+// 0 now
+// 30 30 seconds earlier
+// 80 a minute earlier
+// 340 5 minutes earlier
+// 400 undefined
+func RelTimeMagnitudes(a, b time.Time, albl, blbl string, magnitudes []Magnitude) string {
lbl := albl
diff := b.Unix() - a.Unix()
@@ -70,6 +115,10 @@
return magnitudes[i].d > diff
})
+ if n >= len(magnitudes) {
+ return "undefined"
+ }
+
mag := magnitudes[n]
args := []interface{}{}
escaped := false
diff --git a/times_test.go b/times_test.go
index 528daa4..edcb4a2 100644
--- a/times_test.go
+++ b/times_test.go
@@ -69,3 +69,31 @@
t.Errorf("Expected a long while from now, got %q", x)
}
}
+
+func TestRelTimeMagnitudes(t *testing.T) {
+ magnitudes := []Magnitude{
+ NewMagnitude(1, "now", 1),
+ NewMagnitude(2, "1s %s", 1),
+ NewMagnitude(Minute, "s %s", 1),
+ NewMagnitude(2*Minute, "1m %s", 1),
+ NewMagnitude(Hour, "%dm %s", Minute),
+ NewMagnitude(2*Hour, "1h %s", 1),
+ NewMagnitude(Day, "%dh %s", Hour),
+ NewMagnitude(2*Day, "1D %s", 1),
+ NewMagnitude(Month, "%dD %s", Day),
+ NewMagnitude(2*Month, "1M %s", 1),
+ NewMagnitude(Year, "%dM %s", Month),
+ NewMagnitude(18*Month, "1Y %s", 1),
+ NewMagnitude(2*Year, "2Y %s", 1),
+ }
+ now := time.Now().Unix()
+ testList{
+ {"now", RelTimeMagnitudes(time.Unix(now, 0), time.Now(), "ago", "later", magnitudes), "now"},
+ {"1 second from now", RelTimeMagnitudes(time.Unix(now+1, 0), time.Now(), "ago", "later", magnitudes), "1s later"},
+ // Unit week has been removed from magnitudes
+ {"1 week ago", RelTimeMagnitudes(time.Unix(now-12*Day, 0), time.Now(), "ago", "", magnitudes), "12D ago"},
+ {"3 months ago", RelTimeMagnitudes(time.Unix(now-99*Day, 0), time.Now(), "ago", "later", magnitudes), "3M ago"},
+ {"1 year ago", RelTimeMagnitudes(time.Unix(now-365*Day, 0), time.Now(), "", "later", magnitudes), "1Y "},
+ {"out of defined magnitudes", RelTimeMagnitudes(time.Unix(now+LongTime, 0), time.Now(), "ago", "later", magnitudes), "undefined"},
+ }.validate(t)
+}