github.com/fraugster/parquet-go@v0.12.0/int96_time.go (about) 1 package goparquet 2 3 import ( 4 "encoding/binary" 5 "time" 6 ) 7 8 const ( 9 jan011970 = 2440588 10 secPerDay = 24 * 60 * 60 11 ) 12 13 var ( 14 tsUnixEpoch = time.Unix(0, 0) 15 ) 16 17 func timeToJD(t time.Time) (uint32, uint64) { 18 days := t.Unix() / secPerDay 19 nSecs := t.UnixNano() - (days * secPerDay * int64(time.Second)) 20 21 // unix time starts from Jan 1, 1970 AC, this day is 2440588 day after the Jan 1, 4713 BC 22 return uint32(days) + jan011970, uint64(nSecs) 23 } 24 25 func jdToTime(jd uint32, nsec uint64) time.Time { 26 sec := int64(jd-jan011970) * secPerDay 27 return time.Unix(sec, int64(nsec)) 28 } 29 30 // Int96ToTime is a utility function to convert a Int96 Julian Date timestamp (https://en.wikipedia.org/wiki/Julian_day) to a time.Time. 31 // Please be aware that this function is limited to timestamps after the Unix epoch (Jan 01 1970 00:00:00 UTC) and cannot 32 // convert timestamps before that. The returned time does not contain a monotonic clock reading and is in the machine's current time zone. 33 func Int96ToTime(parquetDate [12]byte) time.Time { 34 nano := binary.LittleEndian.Uint64(parquetDate[:8]) 35 dt := binary.LittleEndian.Uint32(parquetDate[8:]) 36 37 return jdToTime(dt, nano) 38 } 39 40 // TimeToInt96 is a utility function to convert a time.Time to an Int96 Julian Date timestamp (https://en.wikipedia.org/wiki/Julian_day). 41 // Please be aware that this function is limited to timestamps after the Unix epoch (Jan 01 1970 00:00:00 UTC) and cannot convert 42 // timestamps before that. 43 func TimeToInt96(t time.Time) [12]byte { 44 var parquetDate [12]byte 45 days, nSecs := timeToJD(t) 46 binary.LittleEndian.PutUint64(parquetDate[:8], nSecs) 47 binary.LittleEndian.PutUint32(parquetDate[8:], days) 48 49 return parquetDate 50 } 51 52 // IsAfterUnixEpoch tests if a timestamp can be converted into Julian Day format, i.e. is it greater than 01-01-1970? 53 // Timestamps before this when converted will be corrupted when read back. 54 func IsAfterUnixEpoch(t time.Time) bool { 55 return t.After(tsUnixEpoch) 56 }