-
Notifications
You must be signed in to change notification settings - Fork 3
/
time.go
152 lines (135 loc) · 3.98 KB
/
time.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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
// Copyright 2016 Google LLC
// Copyright 2019 Emir Ribic
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package dt
import (
"database/sql/driver"
"fmt"
"time"
)
// A Time represents a time with nanosecond precision.
//
// This type does not include location information, and therefore does not
// describe a unique moment in time.
//
// This type exists to represent the TIME type in storage-based APIs like BigQuery.
// Most operations on Times are unlikely to be meaningful. Prefer the DateTime type.
type Time struct {
Hour int // The hour of the day in 24-hour format; range [0-23]
Minute int // The minute of the hour; range [0-59]
Valid bool
}
// TimeOf returns the Time representing the time of day in which a time occurs
// in that time's location. It ignores the date.
func TimeOf(t time.Time) Time {
tm := Time{Valid: !t.IsZero()}
tm.Hour, tm.Minute, _ = t.Clock()
return tm
}
// ParseTime parses a string and returns the time value it represents.
// ParseTime accepts an extended form of the RFC3339 partial-time format. After
// the HH:MM:SS part of the string, an optional fractional part may appear,
// consisting of a decimal point followed by one to nine decimal digits.
// (RFC3339 admits only one digit after the decimal point).
func ParseTime(s string) (Time, error) {
t, err := time.Parse("15:04", s)
if err != nil {
t, err := time.Parse("15:04:05", s)
return TimeOf(t), err
}
return TimeOf(t), nil
}
// String returns the date in the format described in ParseTime.
// If Valid is not true, it will return empty string
func (t Time) String() string {
if t.Valid {
return fmt.Sprintf("%02d:%02d", t.Hour, t.Minute)
}
return ""
}
// ToDate converts Time into time.Time
func (t Time) ToDate() time.Time {
return time.Date(0, 0, 0, t.Hour, t.Minute, 0, 0, time.UTC)
}
// After checks if instance of t is after tm
func (t Time) After(tm Time) bool {
if t.Hour == tm.Hour {
return t.Minute > tm.Minute
}
return t.Hour > tm.Hour
}
// After checks if instance of t is before tm
func (t Time) Before(tm Time) bool {
if t.Hour == tm.Hour {
return t.Minute < tm.Minute
}
return t.Hour < tm.Hour
}
// Subtract returns difference between t and t2 in minutes
func (t Time) Subtract(t2 Time) int {
return (t.Hour-t2.Hour)*60 + t.Minute - t2.Minute
}
// MarshalText implements the encoding.TextMarshaler interface.
// The output is the result of d.String().
func (t Time) MarshalText() ([]byte, error) {
return []byte(t.String()), nil
}
// UnmarshalText implements the encoding.TextUnmarshaler interface.
// The time is expected to be a string in a format accepted by ParseTime.
func (t *Time) UnmarshalText(data []byte) error {
var err error
*t, err = ParseTime(string(data))
return err
}
// Value implements valuer interface
func (t Time) Value() (driver.Value, error) {
if t.Valid {
return driver.Value(t.String()), nil
}
return nil, nil
}
// Scan implements sql scan interface
func (t *Time) Scan(value interface{}) error {
if value == nil {
return nil
}
switch v := value.(type) {
case []byte:
tm, err := ParseTime(string(v))
if err != nil {
return err
}
*t = tm
return nil
case string:
tm, err := ParseTime(v)
if err != nil {
return err
}
*t = tm
return nil
}
return fmt.Errorf("Can't convert %T to Time", value)
}
// Compare compares t and t2. If t is before t2, it returns -1;
// if t is after t2, it returns +1; otherwise it returns 0.
func (t Time) Compare(t2 Time) int {
if t.Before(t2) {
return -1
}
if t.After(t2) {
return +1
}
return 0
}