/
duration.go
99 lines (90 loc) · 2.68 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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Protocol Buffers - Google's data interchange format
// Copyright 2008 Google Inc. All rights reserved.
// Copyright 2022 Teppei Fukuda. All rights reserved.
// https://developers.google.com/protocol-buffers/
package durationpb
import (
"math"
"time"
"google.golang.org/protobuf/runtime/protoimpl"
)
// New constructs a new Duration from the provided time.Duration.
func New(d time.Duration) *Duration {
nanos := d.Nanoseconds()
secs := nanos / 1e9
nanos -= secs * 1e9
return &Duration{Seconds: int64(secs), Nanos: int32(nanos)}
}
// AsDuration converts x to a time.Duration,
// returning the closest duration value in the event of overflow.
func (x *Duration) AsDuration() time.Duration {
secs := x.GetSeconds()
nanos := x.GetNanos()
d := time.Duration(secs) * time.Second
// TODO: "__multi3" is not exported in module 'env'
//overflow := d/time.Second != time.Duration(secs)
d += time.Duration(nanos) * time.Nanosecond
overflow := secs < 0 && nanos < 0 && d > 0
overflow = overflow || (secs > 0 && nanos > 0 && d < 0)
if overflow {
switch {
case secs < 0:
return time.Duration(math.MinInt64)
case secs > 0:
return time.Duration(math.MaxInt64)
}
}
return d
}
// IsValid reports whether the duration is valid.
// It is equivalent to CheckValid == nil.
func (x *Duration) IsValid() bool {
return x.check() == 0
}
// CheckValid returns an error if the duration is invalid.
// In particular, it checks whether the value is within the range of
// -10000 years to +10000 years inclusive.
// An error is reported for a nil Duration.
func (x *Duration) CheckValid() error {
switch x.check() {
case invalidNil:
return protoimpl.X.NewError("invalid nil Duration")
case invalidUnderflow:
return protoimpl.X.NewError("duration (%v) exceeds -10000 years", x)
case invalidOverflow:
return protoimpl.X.NewError("duration (%v) exceeds +10000 years", x)
case invalidNanosRange:
return protoimpl.X.NewError("duration (%v) has out-of-range nanos", x)
case invalidNanosSign:
return protoimpl.X.NewError("duration (%v) has seconds and nanos with different signs", x)
default:
return nil
}
}
const (
_ = iota
invalidNil
invalidUnderflow
invalidOverflow
invalidNanosRange
invalidNanosSign
)
func (x *Duration) check() uint {
const absDuration = 315576000000 // 10000yr * 365.25day/yr * 24hr/day * 60min/hr * 60sec/min
secs := x.GetSeconds()
nanos := x.GetNanos()
switch {
case x == nil:
return invalidNil
case secs < -absDuration:
return invalidUnderflow
case secs > +absDuration:
return invalidOverflow
case nanos <= -1e9 || nanos >= +1e9:
return invalidNanosRange
case (secs > 0 && nanos < 0) || (secs < 0 && nanos > 0):
return invalidNanosSign
default:
return 0
}
}