depot/go/trains/webapi/utils.go

200 lines
4 KiB
Go
Raw Normal View History

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()
}