| 1 | package chronos |
| 2 | |
| 3 | import "time" |
| 4 | |
| 5 | // Span is a calendar-aware amount of time. Calendar components |
| 6 | // (Years, Months, Days) are added via [time.Time.AddDate], which |
| 7 | // makes them sensitive to month lengths, leap years, and daylight |
| 8 | // saving; the sub-day Dur is added as an absolute [time.Duration]. |
| 9 | type Span struct { |
| 10 | Years int |
| 11 | Months int |
| 12 | Days int |
| 13 | Dur time.Duration |
| 14 | } |
| 15 | |
| 16 | // Unit spans. Sub-day units live in Dur; Day and Week are calendar days; |
| 17 | // Month and Year are calendar units resolved by [time.Time.AddDate]. |
| 18 | var ( |
| 19 | Nanosecond = Span{Dur: time.Nanosecond} |
| 20 | Microsecond = Span{Dur: time.Microsecond} |
| 21 | Millisecond = Span{Dur: time.Millisecond} |
| 22 | Second = Span{Dur: time.Second} |
| 23 | Minute = Span{Dur: time.Minute} |
| 24 | Hour = Span{Dur: time.Hour} |
| 25 | Day = Span{Days: 1} |
| 26 | Week = Span{Days: 7} |
| 27 | Month = Span{Months: 1} |
| 28 | Year = Span{Years: 1} |
| 29 | ) |
| 30 | |
| 31 | // Years returns a [Span] of n calendar years. |
| 32 | func Years(n int) Span { return Span{Years: n} } |
| 33 | |
| 34 | // Months returns a [Span] of n calendar months. |
| 35 | func Months(n int) Span { return Span{Months: n} } |
| 36 | |
| 37 | // Weeks returns a [Span] of n weeks (7n calendar days). |
| 38 | func Weeks(n int) Span { return Span{Days: 7 * n} } |
| 39 | |
| 40 | // Days returns a [Span] of n calendar days. |
| 41 | func Days(n int) Span { return Span{Days: n} } |
| 42 | |
| 43 | // Hours returns a [Span] of n hours of absolute duration. |
| 44 | func Hours(n int) Span { return Span{Dur: time.Duration(n) * time.Hour} } |
| 45 | |
| 46 | // Minutes returns a [Span] of n minutes of absolute duration. |
| 47 | func Minutes(n int) Span { return Span{Dur: time.Duration(n) * time.Minute} } |
| 48 | |
| 49 | // Seconds returns a [Span] of n seconds of absolute duration. |
| 50 | func Seconds(n int) Span { return Span{Dur: time.Duration(n) * time.Second} } |
| 51 | |
| 52 | // Add returns the component-wise sum of s and o. |
| 53 | func (s Span) Add(o Span) Span { |
| 54 | return Span{ |
| 55 | Years: s.Years + o.Years, |
| 56 | Months: s.Months + o.Months, |
| 57 | Days: s.Days + o.Days, |
| 58 | Dur: s.Dur + o.Dur, |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | // Mul returns s with every component scaled by n. |
| 63 | func (s Span) Mul(n int) Span { |
| 64 | return Span{ |
| 65 | Years: s.Years * n, |
| 66 | Months: s.Months * n, |
| 67 | Days: s.Days * n, |
| 68 | Dur: s.Dur * time.Duration(n), |
| 69 | } |
| 70 | } |
| 71 | |
| 72 | // IsZero reports whether s has no calendar and no duration component. |
| 73 | func (s Span) IsZero() bool { |
| 74 | return s.Years == 0 && s.Months == 0 && s.Days == 0 && s.Dur == 0 |
| 75 | } |
| 76 | |
| 77 | // addTo adds s to t: calendar components via [time.Time.AddDate] |
| 78 | // (subject to its month-end and DST normalization) then Dur as an |
| 79 | // absolute duration. The location of t is preserved. |
| 80 | func (s Span) addTo(t time.Time) time.Time { |
| 81 | return t.AddDate(s.Years, s.Months, s.Days).Add(s.Dur) |
| 82 | } |
| 83 | |