mirror of
https://github.com/taigrr/most-specific-period.git
synced 2026-04-02 03:38:41 -07:00
72 lines
1.9 KiB
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
|
|
}
|