74 lines
2 KiB
Go
74 lines
2 KiB
Go
package darwindb
|
|
|
|
import (
|
|
"fmt"
|
|
"time"
|
|
|
|
"hg.lukegb.com/lukegb/depot/go/trains/darwin"
|
|
)
|
|
|
|
// secondsify adds :00 onto the end of a string if it's HH:MM formatted, otherwise does nothing.
|
|
func secondsify(ts string) string {
|
|
if len(ts) == 5 { // xx:xx (no seconds)
|
|
return ts + ":00"
|
|
}
|
|
return ts
|
|
}
|
|
|
|
// startTime takes a train and ascertains its "start time".
|
|
func startTime(s *darwin.Schedule) (time.Time, error) {
|
|
// We assume these are sensibly sorted by Darwin.
|
|
if len(s.CallingPoints) == 0 {
|
|
return time.Time{}, fmt.Errorf("no calling points")
|
|
}
|
|
cp := s.CallingPoints[0]
|
|
|
|
var ts string
|
|
tsCandidates := []string{cp.WTD, cp.PTD, cp.WTP, cp.WTA, cp.PTA}
|
|
for _, tsc := range tsCandidates {
|
|
if tsc != "" {
|
|
ts = tsc
|
|
}
|
|
}
|
|
if ts == "" {
|
|
return time.Time{}, fmt.Errorf("failed to find a suitable timestamp in first calling point")
|
|
}
|
|
|
|
ts = fmt.Sprintf("%v %v", s.SSD, secondsify(ts))
|
|
|
|
t, err := time.ParseInLocation("2006-01-02 15:04:05", ts, darwin.London)
|
|
if err != nil {
|
|
return time.Time{}, fmt.Errorf("parsing start time %q: %w", ts, err)
|
|
}
|
|
return t, nil
|
|
}
|
|
|
|
// timeToTimestamp takes a string HH:MM and places it appropriately given the approximate 'start time' of the train.
|
|
func timeToTimestamp(ts string, startTime time.Time) *time.Time {
|
|
if ts == "" {
|
|
return nil
|
|
}
|
|
ts = secondsify(ts)
|
|
|
|
t, err := time.ParseInLocation("2006-01-02 15:04:05", startTime.Format("2006-01-02 ")+ts, darwin.London)
|
|
if err != nil {
|
|
return nil
|
|
}
|
|
|
|
// Follow Darwin rules for determining time skips
|
|
// https://wiki.openraildata.com/index.php/Darwin:Schedule_Element#Ordering
|
|
difference := t.Sub(startTime)
|
|
switch {
|
|
case difference > -6*time.Hour && difference < 18*time.Hour:
|
|
return &t
|
|
case difference <= -6*time.Hour:
|
|
// e.g. 08:00 start time, 01:00 time "now" (-7 hrs) -- add a day
|
|
t = t.AddDate(0, 0, 1)
|
|
return &t
|
|
case difference >= 18*time.Hour:
|
|
// e.g. 01:00 start time, 22:00 time "now" (+18 hrs) -- sub a day
|
|
t = t.AddDate(0, 0, -1)
|
|
return &t
|
|
}
|
|
panic(fmt.Sprintf("unhandled difference %v", difference))
|
|
}
|