-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathduration.go
78 lines (66 loc) · 2.12 KB
/
duration.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
package pqinterval
import (
"database/sql/driver"
"errors"
"math"
"time"
)
// Duration is a time.Duration alias that supports the driver.Valuer and
// sql.Scanner interfaces.
type Duration time.Duration
// ErrTooBig is returned by Interval.Duration and Duration.Scan if the
// interval would overflow a time.Duration.
var ErrTooBig = errors.New("interval overflows time.Duration")
// Duration converts an Interval into a time.Duration with the same
// semantics as `EXTRACT(EPOCH from <interval>)` in PostgreSQL.
func (ival Interval) Duration() (time.Duration, error) {
dur := int64(ival.Years())
if dur > math.MaxInt64/nsPerYr || dur < math.MinInt64/nsPerYr {
return 0, ErrTooBig
}
dur *= hrsPerYr
dur += int64(ival.hrs)
if dur > math.MaxInt64/int64(time.Hour) || dur < math.MinInt64/int64(time.Hour) {
return 0, ErrTooBig
}
dur *= int64(time.Hour)
us := ival.Microseconds() * int64(time.Microsecond)
if dur > 0 {
if math.MaxInt64-dur < us {
return 0, ErrTooBig
}
} else {
if math.MinInt64-dur > us {
return 0, ErrTooBig
}
}
dur += us
return time.Duration(dur), nil
}
// Scan implements sql.Scanner.
func (d *Duration) Scan(src interface{}) error {
ival := Interval{}
err := (&ival).Scan(src)
if err != nil {
return err
}
result, err := ival.Duration()
if err != nil {
return err
}
*d = Duration(result)
return nil
}
// Value implements driver.Valuer.
func (d Duration) Value() (driver.Value, error) {
var years, months, days, hours, minutes, seconds, milliseconds, microseconds, nanoseconds int64
nanoseconds = int64(d / Duration(time.Nanosecond))
years, nanoseconds = divmod(nanoseconds, int64(time.Hour*hrsPerYr))
days, nanoseconds = divmod(nanoseconds, int64(time.Hour*24))
hours, nanoseconds = divmod(nanoseconds, int64(time.Hour))
minutes, nanoseconds = divmod(nanoseconds, int64(time.Minute))
seconds, nanoseconds = divmod(nanoseconds, int64(time.Second))
milliseconds, nanoseconds = divmod(nanoseconds, int64(time.Millisecond))
microseconds, _ = divmod(nanoseconds, int64(time.Microsecond))
return formatInput(years, months, days, hours, minutes, seconds, milliseconds, microseconds), nil
}