1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
|
package xlsx
import (
"airlines/pkg/model"
"errors"
"strconv"
"strings"
"time"
"airlines/pkg/airports"
)
type Ticket struct {
Sheet string
Passenger string
Title string
FlightNumber string
FromCity string
FromCountry string
FromAirport string
FromCoords model.LatLong
ToCity string
ToCountry string
ToAirport string
ToCoords model.LatLong
FlightDate string // expected YYYY-MM-DD
FlightTime string // expected HH-MM or HH:MM
PNR string
Card string
TicketNumber string
}
func (t Ticket) DateTime() (time.Time, *time.Location, error) {
loc := t.inferLocationFromAirports()
date := strings.TrimLeft(strings.TrimSpace(t.FlightDate), "'")
hm := strings.TrimLeft(strings.TrimSpace(t.FlightTime), "'")
hm = strings.ReplaceAll(hm, "-", ":")
if date == "" || hm == "" {
return time.Time{}, loc, errors.New("missing FlightDate or FlightTime")
}
ts, err := time.ParseInLocation("2006-01-02 15:04", date+" "+hm, loc)
return ts, loc, err
}
func (t Ticket) inferLocationFromAirports() *time.Location {
if loc := iataToLocation(t.FromAirport); loc != nil {
return loc
}
if loc := iataToLocation(t.ToAirport); loc != nil {
return loc
}
return time.Local
}
func iataToLocation(code string) *time.Location {
iata := strings.ToUpper(strings.TrimSpace(code))
if len(iata) != 3 {
return nil
}
ap, err := airports.LookupIATA(iata)
if err != nil {
return nil
}
// prefer IATA tz name
if tz := strings.TrimSpace(ap.Tz); tz != "" && tz != `\N` {
if loc, err := time.LoadLocation(tz); err == nil {
return loc
}
}
// fallback to fixed offset (no DST)
if ap.Timezone != 0 {
sec := int(ap.Timezone * 3600.0)
return time.FixedZone("UTC"+offsetLabel(sec), sec)
}
return nil
}
func offsetLabel(sec int) string {
sign := "+"
if sec < 0 {
sign = "-"
sec = -sec
}
h := sec / 3600
m := (sec % 3600) / 60
return sign + two(h) + ":" + two(m)
}
func two(x int) string {
if x < 10 {
return "0" + strconv.Itoa(x)
}
return strconv.Itoa(x)
}
|