go.temporal.io/server@v1.23.0/common/primitives/timestamp/time.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package timestamp 26 27 import ( 28 "time" 29 30 "google.golang.org/protobuf/types/known/durationpb" 31 "google.golang.org/protobuf/types/known/timestamppb" 32 ) 33 34 // Timestamp provides easy conversions and utility comparison functions 35 // making go to proto time comparison straightforward 36 type Timestamp struct { 37 // one of 38 protoTime *timestamppb.Timestamp 39 goTime time.Time 40 } 41 42 // TimestampFromProto returns a Timestamp from proto time 43 // noinspection GoNameStartsWithPackageName 44 func TimestampFromProto(ts *timestamppb.Timestamp) *Timestamp { 45 // todo: should we validate against proto min/max time here? 46 return &Timestamp{ 47 protoTime: ×tamppb.Timestamp{ 48 Seconds: ts.Seconds, 49 Nanos: ts.Nanos, 50 }, 51 } 52 } 53 54 // TimestampFromTimePtr returns a Timestamp from a time.time 55 // noinspection GoNameStartsWithPackageName 56 func TimestampFromTime(t time.Time) *Timestamp { 57 // todo: should we validate against proto min/max time here? 58 c := time.Unix(0, t.UnixNano()).UTC() 59 return &Timestamp{ 60 goTime: c, 61 } 62 } 63 64 // TimestampFromTimePtr returns a Timestamp from a time.time 65 // noinspection GoNameStartsWithPackageName 66 func TimestampFromTimePtr(t *time.Time) *Timestamp { 67 // todo: should we validate against proto min/max time here? 68 c := time.Unix(0, t.UnixNano()).UTC() 69 return &Timestamp{ 70 goTime: c, 71 } 72 } 73 74 // TimestampNow returns a timestamp that represents Now() 75 // noinspection GoNameStartsWithPackageName 76 func TimestampNow() *Timestamp { 77 return &Timestamp{ 78 protoTime: timestamppb.New(time.Now()), 79 } 80 } 81 82 // TimestampNowAddSeconds returns a timestamp that represents Now() + some number of seconds 83 // noinspection GoNameStartsWithPackageName 84 func TimestampNowAddSeconds(seconds int64) *Timestamp { 85 t := TimestampNow() 86 t.protoTime.Seconds += seconds 87 return t 88 } 89 90 // TimestampEpoch returns the unix epoch -TimestampFromTime(time.Unix(0, 0)).UTC() 91 // noinspection GoNameStartsWithPackageName 92 func TimestampEpoch() *Timestamp { 93 epoch := time.Unix(0, 0).UTC() 94 return TimestampFromTimePtr(&epoch) 95 } 96 97 // ToProto returns the proto representation 98 // noinspection GoReceiverNames 99 func (t *Timestamp) ToProto() *timestamppb.Timestamp { 100 if t.protoTime != nil { 101 return t.protoTime 102 } 103 104 return timestamppb.New(t.goTime) 105 } 106 107 // ToTime returns the time.time representation 108 // noinspection GoReceiverNames 109 func (t *Timestamp) ToTime() time.Time { 110 if !t.goTime.IsZero() { 111 return t.goTime 112 } 113 114 return t.protoTime.AsTime() 115 } 116 117 // Before returns true when t1 is after t2, false otherwise 118 // noinspection GoReceiverNames 119 func (t1 *Timestamp) After(t2 *Timestamp) bool { 120 if !t1.goTime.IsZero() && !t2.goTime.IsZero() { 121 // both go time 122 return t1.goTime.After(t2.goTime) 123 124 } 125 126 return t1.UnixNano() > t2.UnixNano() 127 } 128 129 // Before returns true when t1 is before t2, false otherwise 130 // noinspection GoReceiverNames 131 func (t1 *Timestamp) Before(t2 *Timestamp) bool { 132 if !t1.goTime.IsZero() && !t2.goTime.IsZero() { 133 // both go time 134 return t1.goTime.Before(t2.goTime) 135 136 } 137 138 return t1.UnixNano() < t2.UnixNano() 139 } 140 141 // SamesAs returns true when t1 is the same time as t2, false otherwise 142 // noinspection GoReceiverNames 143 func (t1 *Timestamp) SameAs(t2 *Timestamp) bool { 144 if !t1.goTime.IsZero() && !t2.goTime.IsZero() { 145 // both go time 146 return t1.goTime.Equal(t2.goTime) 147 148 } 149 150 return t1.UnixNano() == t2.UnixNano() 151 } 152 153 // UnixNano returns the int64 representation of nanoseconds since 1970 (see time.UnixNano) 154 // noinspection GoReceiverNames 155 func (t *Timestamp) UnixNano() int64 { 156 if !t.goTime.IsZero() { 157 return t.goTime.UnixNano() 158 } 159 160 return t.protoTime.Seconds*time.Second.Nanoseconds() + int64(t.protoTime.Nanos) 161 } 162 163 func TimePtr(t time.Time) *timestamppb.Timestamp { 164 return timestamppb.New(t) 165 } 166 167 func TimeValue(t *timestamppb.Timestamp) time.Time { 168 if t == nil { 169 return time.Time{} 170 } 171 return t.AsTime() 172 } 173 174 func DurationValue(d *durationpb.Duration) time.Duration { 175 if d == nil { 176 return 0 177 } 178 return d.AsDuration() 179 } 180 181 func MinDurationPtr(d1 *durationpb.Duration, d2 *durationpb.Duration) *durationpb.Duration { 182 res := min(DurationValue(d1), DurationValue(d2)) 183 return durationpb.New(res) 184 } 185 186 func RoundUp(d time.Duration) time.Duration { 187 res := d.Truncate(time.Second) 188 if res == d { 189 return d 190 } 191 return res + time.Second 192 } 193 194 func UnixOrZeroTime(nanos int64) time.Time { 195 if nanos <= 0 { 196 nanos = 0 197 } 198 199 return time.Unix(0, nanos).UTC() 200 } 201 202 func UnixOrZeroTimePtr(nanos int64) *timestamppb.Timestamp { 203 return TimePtr(UnixOrZeroTime(nanos)) 204 } 205 206 func TimeNowPtrUtcAddDuration(t time.Duration) *timestamppb.Timestamp { 207 return TimePtr(time.Now().UTC().Add(t)) 208 } 209 210 func TimeNowPtrUtcAddSeconds(seconds int) *timestamppb.Timestamp { 211 return TimePtr(time.Now().UTC().Add(time.Second * time.Duration(seconds))) 212 } 213 214 func TimeNowPtrUtc() *timestamppb.Timestamp { 215 return TimePtr(time.Now().UTC()) 216 }