-
Notifications
You must be signed in to change notification settings - Fork 1
/
timeofday.go
92 lines (81 loc) · 1.88 KB
/
timeofday.go
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
package nmea
// FIXME what happens to second on GPS leap second?
import (
"fmt"
"time"
)
type TimeOfDay struct {
Hour int
Minute int
Second int
Nanosecond int
}
func (t TimeOfDay) String() string {
return fmt.Sprintf("%02d:%02d:%02d.%09d", t.Hour, t.Minute, t.Second, t.Nanosecond)
}
func (t TimeOfDay) SinceMidnight() time.Duration {
return time.Duration(t.Hour)*time.Hour +
time.Duration(t.Minute)*time.Minute +
time.Duration(t.Second)*time.Second +
time.Duration(t.Nanosecond)*time.Nanosecond
}
func (t TimeOfDay) Valid() bool {
if t.Hour < 0 || 23 < t.Hour {
return false
}
if t.Minute < 0 || 59 < t.Minute {
return false
}
// FIXME what happens to second on GPS leap second?
if t.Second < 0 || 60 < t.Second {
return false
}
if t.Nanosecond < 0 || 99999999 < t.Nanosecond {
return false
}
return true
}
func (t *Tokenizer) CommaOptionalTimeOfDay() Optional[TimeOfDay] {
t.Comma()
return t.OptionalTimeOfDay()
}
func (t *Tokenizer) CommaTimeOfDay() TimeOfDay {
t.Comma()
return t.TimeOfDay()
}
func (t *Tokenizer) OptionalTimeOfDay() Optional[TimeOfDay] {
if t.err != nil {
return Optional[TimeOfDay]{}
}
if t.pos == len(t.data) {
return Optional[TimeOfDay]{}
}
if t.data[t.pos] == ',' {
return Optional[TimeOfDay]{}
}
return NewOptional(t.TimeOfDay())
}
func (t *Tokenizer) TimeOfDay() TimeOfDay {
hour := t.DecimalDigits(2)
min := t.DecimalDigits(2)
sec, nsec := secondPointNanosecond(t)
return TimeOfDay{
Hour: hour,
Minute: min,
Second: sec,
Nanosecond: nsec,
}
}
func secondPointNanosecond(tok *Tokenizer) (int, int) {
sec := tok.DecimalDigits(2)
numerator, denominator := tok.OptionalPointDecimal()
for denominator < 1000000000 {
numerator *= 10
denominator *= 10
}
if denominator > 1000000000 {
factor := denominator / 1000000000
numerator = (numerator + factor/2) / factor
}
return sec, numerator
}