Files
weatherreporter/internal/timeutil/periods.go

82 lines
1.9 KiB
Go

package timeutil
import (
"fmt"
"strconv"
"strings"
"time"
)
type Period struct {
Start time.Time `json:"start"`
End time.Time `json:"end"`
}
func (p Period) IsValid() bool {
return p.End.After(p.Start)
}
func (p Period) Overlaps(other Period) bool {
return p.Start.Before(other.End) && other.Start.Before(p.End)
}
func (p Period) Contains(t time.Time) bool {
return !t.Before(p.Start) && t.Before(p.End)
}
func (p Period) Intersection(other Period) (Period, bool) {
if !p.Overlaps(other) {
return Period{}, false
}
start := p.Start
if other.Start.After(start) {
start = other.Start
}
end := p.End
if other.End.Before(end) {
end = other.End
}
return Period{Start: start, End: end}, true
}
func ParseClock(value string) (time.Duration, error) {
parts := strings.Split(value, ":")
if len(parts) != 2 {
return 0, fmt.Errorf("expected HH:MM")
}
hour, err := strconv.Atoi(parts[0])
if err != nil {
return 0, fmt.Errorf("invalid hour")
}
minute, err := strconv.Atoi(parts[1])
if err != nil {
return 0, fmt.Errorf("invalid minute")
}
if hour < 0 || hour > 24 {
return 0, fmt.Errorf("hour must be between 00 and 24")
}
if minute < 0 || minute > 59 {
return 0, fmt.Errorf("minute must be between 00 and 59")
}
if hour == 24 && minute != 0 {
return 0, fmt.Errorf("24 is only valid as 24:00")
}
return time.Duration(hour)*time.Hour + time.Duration(minute)*time.Minute, nil
}
func CivilDay(date time.Time, location *time.Location) Period {
local := date.In(location)
start := time.Date(local.Year(), local.Month(), local.Day(), 0, 0, 0, 0, location)
return Period{Start: start, End: start.AddDate(0, 0, 1)}
}
func ClockWindow(date time.Time, location *time.Location, startClock time.Duration, endClock time.Duration) Period {
day := CivilDay(date, location)
start := day.Start.Add(startClock)
end := day.Start.Add(endClock)
if !end.After(start) {
end = end.AddDate(0, 0, 1)
}
return Period{Start: start, End: end}
}