github.com/m3db/m3@v1.5.0/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 }