github.com/m3db/m3@v1.5.1-0.20231129193456-75a402aa583b/src/x/time/unix_nano.go (about)

     1  // Copyright (c) 2017 Uber Technologies, Inc.
     2  //
     3  // Permission is hereby granted, free of charge, to any person obtaining a copy
     4  // of this software and associated documentation files (the "Software"), to deal
     5  // in the Software without restriction, including without limitation the rights
     6  // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     7  // copies of the Software, and to permit persons to whom the Software is
     8  // furnished to do so, subject to the following conditions:
     9  //
    10  // The above copyright notice and this permission notice shall be included in
    11  // all copies or substantial portions of the Software.
    12  //
    13  // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    14  // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    15  // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    16  // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    17  // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    18  // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
    19  // THE SOFTWARE.
    20  
    21  package time
    22  
    23  import (
    24  	"time"
    25  )
    26  
    27  // UnixNano is used to indicate that an int64 stores a unix timestamp at
    28  // nanosecond resolution.
    29  type UnixNano int64
    30  
    31  // ToTime returns a time.ToTime from a UnixNano.
    32  func (u UnixNano) ToTime() time.Time {
    33  	return time.Unix(0, int64(u))
    34  }
    35  
    36  // ToUnixNano returns a UnixNano from a time.Time.
    37  func ToUnixNano(t time.Time) UnixNano {
    38  	return UnixNano(t.UnixNano())
    39  }
    40  
    41  const (
    42  	secondsPerDay = 60 * 60 * 24
    43  	// NB:Number of seconds from epoch to timeZero.
    44  	unixToInternal int64 = (1969*365 + 1969/4 - 1969/100 + 1969/400) * secondsPerDay
    45  )
    46  
    47  // Truncate returns the result of rounding u down to a multiple of d.
    48  // If d <= 1, Truncate returns u unchanged.
    49  func (u UnixNano) Truncate(d time.Duration) UnixNano {
    50  	if d <= 1 {
    51  		return u
    52  	}
    53  
    54  	if d < time.Second && time.Second%(d+d) == 0 {
    55  		return u - UnixNano((time.Duration(u)%time.Second)%d)
    56  	}
    57  
    58  	if d%time.Second != 0 {
    59  		// NB: the time.Truncate implementation for non-rounded durations is fairly
    60  		// complex; considering that it is unlikely that xtime.UnixNanos would be
    61  		// truncated by durations that are neither composed of seconds, or divisors
    62  		// of seconds, this defers to time.Time's implementation of truncation.
    63  		return ToUnixNano(time.Unix(0, int64(u)).Truncate(d))
    64  	}
    65  
    66  	// time.Truncate calculates truncation duration based on timeZero; i.e. from
    67  	// the date: January 1, year 1, 00:00:00.000000000 UTC; so here, the seconds
    68  	// from epoch will need to be converted to this timeframe to calculate the
    69  	// truncation duration.
    70  	var (
    71  		i                   = int64(u)
    72  		sec                 = int64(time.Second)
    73  		nanosToTruncate     = i % sec
    74  		secondsFromTimeZero = i/int64(time.Second) + unixToInternal
    75  		duration            = int64(d / time.Second)
    76  		secondsToTruncate   = (secondsFromTimeZero % duration) * int64(time.Second)
    77  	)
    78  
    79  	return u - UnixNano(secondsToTruncate+nanosToTruncate)
    80  }
    81  
    82  // Sub returns the duration u-o. If the result exceeds the maximum (or minimum)
    83  // value that can be stored in a Duration, the maximum (or minimum) duration
    84  // will be returned.
    85  func (u UnixNano) Sub(o UnixNano) time.Duration {
    86  	return time.Duration(u - o)
    87  }
    88  
    89  // Add returns the time u+d.
    90  func (u UnixNano) Add(d time.Duration) UnixNano {
    91  	return u + UnixNano(d)
    92  }
    93  
    94  // ToNormalizedTime returns the normalized units of time given a time unit.
    95  func (u UnixNano) ToNormalizedTime(d time.Duration) int64 {
    96  	return int64(u) / d.Nanoseconds()
    97  }
    98  
    99  // FromNormalizedTime returns the time given the normalized time units and the time unit.
   100  func (u UnixNano) FromNormalizedTime(d time.Duration) UnixNano {
   101  	return u * UnixNano(d/time.Nanosecond)
   102  }
   103  
   104  // Before reports whether the time instant u is before t.
   105  func (u UnixNano) Before(t UnixNano) bool {
   106  	return u < t
   107  }
   108  
   109  // After reports whether the time instant u is after t.
   110  func (u UnixNano) After(t UnixNano) bool {
   111  	return u > t
   112  }
   113  
   114  // Equal reports whether the time instant u is equal to t.
   115  func (u UnixNano) Equal(t UnixNano) bool {
   116  	return u == t
   117  }
   118  
   119  // IsZero reports whether the time instant u is 0.
   120  func (u UnixNano) IsZero() bool {
   121  	return u == 0
   122  }
   123  
   124  // String returns the time formatted using the format string
   125  //	"2006-01-02 15:04:05.999999999 -0700 MST"
   126  func (u UnixNano) String() string {
   127  	return u.ToTime().UTC().String()
   128  }
   129  
   130  // Format returns the string representation for the time with the given format.
   131  func (u UnixNano) Format(blockTimeFormat string) string {
   132  	return u.ToTime().UTC().Format(blockTimeFormat)
   133  }
   134  
   135  // Seconds returns the seconds for time u, as an int64.
   136  func (u UnixNano) Seconds() int64 {
   137  	return u.ToNormalizedTime(time.Second)
   138  }
   139  
   140  // FromSeconds returns the UnixNano representation of the local Time
   141  // corresponding to the seconds since January 1, 1970 UTC.
   142  func FromSeconds(seconds int64) UnixNano {
   143  	return FromSecondsAndNanos(seconds, 0)
   144  }
   145  
   146  // FromSecondsAndNanos returns the UnixNano representation of the local Time
   147  // corresponding to the seconds and nanoseconds since January 1, 1970 UTC.
   148  func FromSecondsAndNanos(seconds int64, nanos int64) UnixNano {
   149  	return ToUnixNano(time.Unix(seconds, nanos))
   150  }