| 123456789101112131415161718192021222324252627282930313233343536373839404142 |
- package service
- import "time"
- // nextCalendarRenewal returns the next renewal strictly after from, at midnight
- // in loc; a missing day clamps to the month's last, so the 31st comes back (#6106).
- func nextCalendarRenewal(from time.Time, day int, loc *time.Location) time.Time {
- if loc == nil {
- loc = time.UTC
- }
- if day < 1 {
- day = 1
- }
- if day > 31 {
- day = 31
- }
- local := from.In(loc)
- candidate := calendarDay(local.Year(), local.Month(), day, loc)
- if !candidate.After(local) {
- year, month := local.Year(), local.Month()+1
- if month > time.December {
- year, month = year+1, time.January
- }
- candidate = calendarDay(year, month, day, loc)
- }
- return candidate
- }
- // Clamped rather than normalized: time.Date rolls 31 February into March, which
- // is the drift this mode exists to avoid.
- func calendarDay(year int, month time.Month, day int, loc *time.Location) time.Time {
- last := daysInMonth(year, month)
- if day > last {
- day = last
- }
- return time.Date(year, month, day, 0, 0, 0, 0, loc)
- }
- func daysInMonth(year int, month time.Month) int {
- return time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day()
- }
|