@@ -0,0 +1,46 @@
|
||||
// Package daterange resolves recurring calendar windows and normalized dates.
|
||||
package daterange
|
||||
|
||||
import "time"
|
||||
|
||||
// CalendarWindow resolves a recurring month/day range around now. A range whose
|
||||
// start month is after its end month crosses the year boundary.
|
||||
func CalendarWindow(now time.Time, monthFrom int, dayFrom *int, monthTo int, dayTo *int) (time.Time, time.Time) {
|
||||
location := now.Location()
|
||||
startYear := now.Year()
|
||||
if monthFrom > monthTo && int(now.Month()) <= monthTo {
|
||||
startYear--
|
||||
}
|
||||
endYear := startYear
|
||||
if monthFrom > monthTo {
|
||||
endYear++
|
||||
}
|
||||
startDay := 1
|
||||
if dayFrom != nil {
|
||||
startDay = clampDay(startYear, time.Month(monthFrom), *dayFrom)
|
||||
}
|
||||
endDay := daysInMonth(endYear, time.Month(monthTo))
|
||||
if dayTo != nil {
|
||||
endDay = clampDay(endYear, time.Month(monthTo), *dayTo)
|
||||
}
|
||||
return time.Date(startYear, time.Month(monthFrom), startDay, 0, 0, 0, 0, location), time.Date(endYear, time.Month(monthTo), endDay, 23, 59, 59, 0, location)
|
||||
}
|
||||
|
||||
// Date returns value at midnight in its original location.
|
||||
func Date(value time.Time) time.Time {
|
||||
return time.Date(value.Year(), value.Month(), value.Day(), 0, 0, 0, 0, value.Location())
|
||||
}
|
||||
|
||||
func daysInMonth(year int, month time.Month) int {
|
||||
return time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day()
|
||||
}
|
||||
|
||||
func clampDay(year int, month time.Month, day int) int {
|
||||
if maximum := daysInMonth(year, month); day > maximum {
|
||||
return maximum
|
||||
}
|
||||
if day < 1 {
|
||||
return 1
|
||||
}
|
||||
return day
|
||||
}
|
||||
Reference in New Issue
Block a user