Files
most-specific-period/msp/msp.go

72 lines
1.9 KiB
Go

package msp
import (
"sort"
"time"
)
func MostSpecificPeriod(ts time.Time, periods ...Period) (id string, err error) {
// Filter to get only valid periods here
periods = ValidTimePeriods(ts, periods...)
if len(periods) == 0 {
return "", ErrNoValidPeriods
}
// find the shortest duration
d, err := GetDuration(periods[0].GetStartTime(), periods[0].GetEndTime())
for _, x := range periods {
p, err := GetDuration(x.GetStartTime(), x.GetEndTime())
if err == nil && p < d {
d = p
}
}
// find all periods with this shortest duration
var matchingDurations []Period
for _, x := range periods {
p, err := GetDuration(x.GetStartTime(), x.GetEndTime())
if err == nil && p == d {
matchingDurations = append(matchingDurations, x)
}
}
// Find the newest time a period starts
newest := matchingDurations[0].GetStartTime()
for _, x := range matchingDurations {
if x.GetStartTime().After(newest) {
newest = x.GetStartTime()
}
}
// Determine whichever of these periods have the same start time in addtion to duration
var matchingDurationsAndStartTimes []Period
for _, x := range matchingDurations {
if x.GetStartTime() == newest {
matchingDurationsAndStartTimes = append(matchingDurationsAndStartTimes, x)
}
}
// Finally, return the period with the 'last' name lexicographically
var identifiers []string
for _, x := range matchingDurationsAndStartTimes {
identifiers = append(identifiers, x.GetIdentifier())
}
sort.Strings(identifiers)
return identifiers[len(identifiers)-1], nil
}
func GetDuration(start time.Time, end time.Time) (dur time.Duration, err error) {
if start.After(end) {
err = ErrEndAfterStart
}
dur = end.Sub(start)
return dur, err
}
func ValidTimePeriods(ts time.Time, periods ...Period) []Period {
var valid []Period
for _, p := range periods {
start := p.GetStartTime()
end := p.GetEndTime()
if (start.Before(ts) || start.Equal(ts)) && (end.After(ts)) {
valid = append(valid, p)
}
}
return valid
}