200 lines
4 KiB
Go
200 lines
4 KiB
Go
|
package webapi
|
||
|
|
||
|
import (
|
||
|
"fmt"
|
||
|
"time"
|
||
|
|
||
|
"github.com/jackc/pgtype"
|
||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||
|
)
|
||
|
|
||
|
func (toc *TrainOperator) IsEmpty() bool {
|
||
|
return toc == nil || toc.Code == ""
|
||
|
}
|
||
|
|
||
|
func (toc *TrainOperator) Canonicalize() {
|
||
|
if toc == nil {
|
||
|
return
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (loc *Location) IsEmpty() bool {
|
||
|
return loc == nil || loc.Tiploc == ""
|
||
|
}
|
||
|
|
||
|
func (loc *Location) Canonicalize() {
|
||
|
if loc == nil {
|
||
|
return
|
||
|
}
|
||
|
if loc.Operator.IsEmpty() {
|
||
|
loc.Operator = nil
|
||
|
}
|
||
|
loc.Operator.Canonicalize()
|
||
|
}
|
||
|
|
||
|
func (dr *DisruptionReason) IsEmpty() bool {
|
||
|
return dr == nil || dr.Code == 0
|
||
|
}
|
||
|
|
||
|
func (dr *DisruptionReason) Canonicalize() {
|
||
|
if dr == nil {
|
||
|
return
|
||
|
}
|
||
|
if dr.Location.IsEmpty() {
|
||
|
dr.Location = nil
|
||
|
}
|
||
|
dr.Location.Canonicalize()
|
||
|
}
|
||
|
|
||
|
func (sd *ServiceData) Canonicalize() {
|
||
|
if sd.DelayReason.IsEmpty() {
|
||
|
sd.DelayReason = nil
|
||
|
}
|
||
|
sd.DelayReason.Canonicalize()
|
||
|
if sd.CancelReason.IsEmpty() {
|
||
|
sd.CancelReason = nil
|
||
|
}
|
||
|
sd.CancelReason.Canonicalize()
|
||
|
}
|
||
|
|
||
|
func (tz *TimeZone) ToLocation() (*time.Location, error) {
|
||
|
return time.LoadLocation(tz.GetName())
|
||
|
}
|
||
|
|
||
|
func (dt *DateTime) ToTime() (time.Time, error) {
|
||
|
tz := dt.GetTimezone()
|
||
|
if tz == nil {
|
||
|
return time.Time{}, fmt.Errorf("no timezone specified")
|
||
|
}
|
||
|
loc, err := tz.ToLocation()
|
||
|
if err != nil {
|
||
|
return time.Time{}, fmt.Errorf("loading timezone (%s / offset %v): %w", tz.GetName(), tz.GetUtcOffset(), err)
|
||
|
}
|
||
|
return dt.GetTimestamp().AsTime().In(loc), nil
|
||
|
}
|
||
|
|
||
|
func (dt *DateTime) decodeWith(ci *pgtype.ConnInfo, src []byte, dec func(*pgtype.Timestamptz, *pgtype.ConnInfo, []byte) error) error {
|
||
|
dt.Timestamp = nil
|
||
|
dt.Timezone = nil
|
||
|
|
||
|
if src == nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
ttz := &pgtype.Timestamptz{}
|
||
|
if err := dec(ttz, ci, src); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if ttz.Status != pgtype.Present {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
*dt = *(FromTime(ttz.Time))
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (dt *DateTime) DecodeBinary(ci *pgtype.ConnInfo, src []byte) error {
|
||
|
return dt.decodeWith(ci, src, (*pgtype.Timestamptz).DecodeBinary)
|
||
|
}
|
||
|
|
||
|
func (dt *DateTime) DecodeText(ci *pgtype.ConnInfo, src []byte) error {
|
||
|
return dt.decodeWith(ci, src, (*pgtype.Timestamptz).DecodeText)
|
||
|
}
|
||
|
|
||
|
func (dt *DateTime) AssignTo(dst interface{}) error {
|
||
|
if dt == nil {
|
||
|
return pgtype.NullAssignTo(dst)
|
||
|
}
|
||
|
|
||
|
switch dst := dst.(type) {
|
||
|
case (*DateTime):
|
||
|
*dst = *dt
|
||
|
return nil
|
||
|
default:
|
||
|
if nextDst, retry := pgtype.GetAssignToDstType(dst); retry {
|
||
|
return dt.AssignTo(nextDst)
|
||
|
}
|
||
|
return fmt.Errorf("unable to assign to %T, sad trombone", dst)
|
||
|
}
|
||
|
|
||
|
return fmt.Errorf("cannot decode %#v into %T, sad trombone", dt, dst)
|
||
|
}
|
||
|
|
||
|
func FromTime(t time.Time) *DateTime {
|
||
|
zName, zOffset := t.Zone()
|
||
|
tz := &TimeZone{
|
||
|
Name: zName,
|
||
|
UtcOffset: int32(zOffset),
|
||
|
}
|
||
|
|
||
|
return &DateTime{
|
||
|
Timestamp: timestamppb.New(t),
|
||
|
Timezone: tz,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (dt *DateTime) IsZero() bool {
|
||
|
if dt.GetTimestamp() == nil {
|
||
|
return true
|
||
|
}
|
||
|
t, err := dt.ToTime()
|
||
|
if err != nil {
|
||
|
return true
|
||
|
}
|
||
|
return t.IsZero()
|
||
|
}
|
||
|
|
||
|
func (td *TimingData) IsEmpty() bool {
|
||
|
if td == nil {
|
||
|
return true
|
||
|
}
|
||
|
return td.PublicScheduled.IsZero() && td.WorkingScheduled.IsZero() && td.PublicEstimated.IsZero() && td.WorkingEstimated.IsZero() && td.Actual.IsZero()
|
||
|
}
|
||
|
|
||
|
func (td *TimingData) Canonicalize() {
|
||
|
if td == nil {
|
||
|
return
|
||
|
}
|
||
|
ts := []**DateTime{&td.PublicScheduled, &td.WorkingScheduled, &td.PublicEstimated, &td.WorkingEstimated, &td.Actual}
|
||
|
for _, t := range ts {
|
||
|
if *t == nil || (*t).IsZero() {
|
||
|
*t = nil
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (pd *PlatformData) IsEmpty() bool {
|
||
|
return pd.Scheduled == "" && pd.Live == ""
|
||
|
}
|
||
|
|
||
|
func (pd *PlatformData) Canonicalize() {}
|
||
|
|
||
|
func (sl *ServiceLocation) Canonicalize() {
|
||
|
if sl == nil {
|
||
|
return
|
||
|
}
|
||
|
sl.Location.Canonicalize()
|
||
|
if sl.Platform.IsEmpty() {
|
||
|
sl.Platform = nil
|
||
|
}
|
||
|
sl.Platform.Canonicalize()
|
||
|
if sl.FalseDestination.IsEmpty() {
|
||
|
sl.FalseDestination = nil
|
||
|
}
|
||
|
sl.FalseDestination.Canonicalize()
|
||
|
if sl.ArrivalTiming.IsEmpty() {
|
||
|
sl.ArrivalTiming = nil
|
||
|
}
|
||
|
sl.ArrivalTiming.Canonicalize()
|
||
|
if sl.DepartureTiming.IsEmpty() {
|
||
|
sl.DepartureTiming = nil
|
||
|
}
|
||
|
sl.DepartureTiming.Canonicalize()
|
||
|
if sl.PassTiming.IsEmpty() {
|
||
|
sl.PassTiming = nil
|
||
|
}
|
||
|
sl.PassTiming.Canonicalize()
|
||
|
}
|