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: &timestamppb.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  }