github.com/sereiner/library@v0.0.0-20200518095232-1fa3e640cc5f/influxdb/models/time.go (about) 1 package models 2 3 // Helper time methods since parsing time can easily overflow and we only support a 4 // specific time range. 5 6 import ( 7 "fmt" 8 "math" 9 "time" 10 ) 11 12 const ( 13 // MinNanoTime is the minumum time that can be represented. 14 // 15 // 1677-09-21 00:12:43.145224194 +0000 UTC 16 // 17 // The two lowest minimum integers are used as sentinel values. The 18 // minimum value needs to be used as a value lower than any other value for 19 // comparisons and another separate value is needed to act as a sentinel 20 // default value that is unusable by the user, but usable internally. 21 // Because these two values need to be used for a special purpose, we do 22 // not allow users to write points at these two times. 23 MinNanoTime = int64(math.MinInt64) + 2 24 25 // MaxNanoTime is the maximum time that can be represented. 26 // 27 // 2262-04-11 23:47:16.854775806 +0000 UTC 28 // 29 // The highest time represented by a nanosecond needs to be used for an 30 // exclusive range in the shard group, so the maximum time needs to be one 31 // less than the possible maximum number of nanoseconds representable by an 32 // int64 so that we don't lose a point at that one time. 33 MaxNanoTime = int64(math.MaxInt64) - 1 34 ) 35 36 var ( 37 minNanoTime = time.Unix(0, MinNanoTime).UTC() 38 maxNanoTime = time.Unix(0, MaxNanoTime).UTC() 39 40 // ErrTimeOutOfRange gets returned when time is out of the representable range using int64 nanoseconds since the epoch. 41 ErrTimeOutOfRange = fmt.Errorf("time outside range %d - %d", MinNanoTime, MaxNanoTime) 42 ) 43 44 // SafeCalcTime safely calculates the time given. Will return error if the time is outside the 45 // supported range. 46 func SafeCalcTime(timestamp int64, precision string) (time.Time, error) { 47 mult := GetPrecisionMultiplier(precision) 48 if t, ok := safeSignedMult(timestamp, mult); ok { 49 tme := time.Unix(0, t).UTC() 50 return tme, CheckTime(tme) 51 } 52 53 return time.Time{}, ErrTimeOutOfRange 54 } 55 56 // CheckTime checks that a time is within the safe range. 57 func CheckTime(t time.Time) error { 58 if t.Before(minNanoTime) || t.After(maxNanoTime) { 59 return ErrTimeOutOfRange 60 } 61 return nil 62 } 63 64 // Perform the multiplication and check to make sure it didn't overflow. 65 func safeSignedMult(a, b int64) (int64, bool) { 66 if a == 0 || b == 0 || a == 1 || b == 1 { 67 return a * b, true 68 } 69 if a == MinNanoTime || b == MaxNanoTime { 70 return 0, false 71 } 72 c := a * b 73 return c, c/b == a 74 }