]>
Commit | Line | Data |
---|---|---|
15c0b25d AP |
1 | // Go support for Protocol Buffers - Google's data interchange format |
2 | // | |
3 | // Copyright 2016 The Go Authors. All rights reserved. | |
4 | // https://github.com/golang/protobuf | |
5 | // | |
6 | // Redistribution and use in source and binary forms, with or without | |
7 | // modification, are permitted provided that the following conditions are | |
8 | // met: | |
9 | // | |
10 | // * Redistributions of source code must retain the above copyright | |
11 | // notice, this list of conditions and the following disclaimer. | |
12 | // * Redistributions in binary form must reproduce the above | |
13 | // copyright notice, this list of conditions and the following disclaimer | |
14 | // in the documentation and/or other materials provided with the | |
15 | // distribution. | |
16 | // * Neither the name of Google Inc. nor the names of its | |
17 | // contributors may be used to endorse or promote products derived from | |
18 | // this software without specific prior written permission. | |
19 | // | |
20 | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
21 | // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
22 | // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
23 | // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
24 | // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
25 | // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
26 | // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
27 | // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
28 | // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
29 | // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
30 | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
31 | ||
32 | package ptypes | |
33 | ||
34 | // This file implements conversions between google.protobuf.Duration | |
35 | // and time.Duration. | |
36 | ||
37 | import ( | |
38 | "errors" | |
39 | "fmt" | |
40 | "time" | |
41 | ||
42 | durpb "github.com/golang/protobuf/ptypes/duration" | |
43 | ) | |
44 | ||
45 | const ( | |
46 | // Range of a durpb.Duration in seconds, as specified in | |
47 | // google/protobuf/duration.proto. This is about 10,000 years in seconds. | |
48 | maxSeconds = int64(10000 * 365.25 * 24 * 60 * 60) | |
49 | minSeconds = -maxSeconds | |
50 | ) | |
51 | ||
52 | // validateDuration determines whether the durpb.Duration is valid according to the | |
53 | // definition in google/protobuf/duration.proto. A valid durpb.Duration | |
54 | // may still be too large to fit into a time.Duration (the range of durpb.Duration | |
55 | // is about 10,000 years, and the range of time.Duration is about 290). | |
56 | func validateDuration(d *durpb.Duration) error { | |
57 | if d == nil { | |
58 | return errors.New("duration: nil Duration") | |
59 | } | |
60 | if d.Seconds < minSeconds || d.Seconds > maxSeconds { | |
61 | return fmt.Errorf("duration: %v: seconds out of range", d) | |
62 | } | |
63 | if d.Nanos <= -1e9 || d.Nanos >= 1e9 { | |
64 | return fmt.Errorf("duration: %v: nanos out of range", d) | |
65 | } | |
66 | // Seconds and Nanos must have the same sign, unless d.Nanos is zero. | |
67 | if (d.Seconds < 0 && d.Nanos > 0) || (d.Seconds > 0 && d.Nanos < 0) { | |
68 | return fmt.Errorf("duration: %v: seconds and nanos have different signs", d) | |
69 | } | |
70 | return nil | |
71 | } | |
72 | ||
73 | // Duration converts a durpb.Duration to a time.Duration. Duration | |
74 | // returns an error if the durpb.Duration is invalid or is too large to be | |
75 | // represented in a time.Duration. | |
76 | func Duration(p *durpb.Duration) (time.Duration, error) { | |
77 | if err := validateDuration(p); err != nil { | |
78 | return 0, err | |
79 | } | |
80 | d := time.Duration(p.Seconds) * time.Second | |
81 | if int64(d/time.Second) != p.Seconds { | |
82 | return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) | |
83 | } | |
84 | if p.Nanos != 0 { | |
107c1cdb | 85 | d += time.Duration(p.Nanos) * time.Nanosecond |
15c0b25d AP |
86 | if (d < 0) != (p.Nanos < 0) { |
87 | return 0, fmt.Errorf("duration: %v is out of range for time.Duration", p) | |
88 | } | |
89 | } | |
90 | return d, nil | |
91 | } | |
92 | ||
93 | // DurationProto converts a time.Duration to a durpb.Duration. | |
94 | func DurationProto(d time.Duration) *durpb.Duration { | |
95 | nanos := d.Nanoseconds() | |
96 | secs := nanos / 1e9 | |
97 | nanos -= secs * 1e9 | |
98 | return &durpb.Duration{ | |
99 | Seconds: secs, | |
100 | Nanos: int32(nanos), | |
101 | } | |
102 | } |