Matthias Andreas Benkard | 832a54e | 2019-01-29 09:27:38 +0100 | [diff] [blame^] | 1 | // Copyright 2014 Google Inc. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style |
| 3 | // license that can be found in the LICENSE file. |
| 4 | |
| 5 | package uuid |
| 6 | |
| 7 | import ( |
| 8 | "encoding/binary" |
| 9 | "sync" |
| 10 | "time" |
| 11 | ) |
| 12 | |
| 13 | // A Time represents a time as the number of 100's of nanoseconds since 15 Oct |
| 14 | // 1582. |
| 15 | type Time int64 |
| 16 | |
| 17 | const ( |
| 18 | lillian = 2299160 // Julian day of 15 Oct 1582 |
| 19 | unix = 2440587 // Julian day of 1 Jan 1970 |
| 20 | epoch = unix - lillian // Days between epochs |
| 21 | g1582 = epoch * 86400 // seconds between epochs |
| 22 | g1582ns100 = g1582 * 10000000 // 100s of a nanoseconds between epochs |
| 23 | ) |
| 24 | |
| 25 | var ( |
| 26 | timeMu sync.Mutex |
| 27 | lasttime uint64 // last time we returned |
| 28 | clock_seq uint16 // clock sequence for this run |
| 29 | |
| 30 | timeNow = time.Now // for testing |
| 31 | ) |
| 32 | |
| 33 | // UnixTime converts t the number of seconds and nanoseconds using the Unix |
| 34 | // epoch of 1 Jan 1970. |
| 35 | func (t Time) UnixTime() (sec, nsec int64) { |
| 36 | sec = int64(t - g1582ns100) |
| 37 | nsec = (sec % 10000000) * 100 |
| 38 | sec /= 10000000 |
| 39 | return sec, nsec |
| 40 | } |
| 41 | |
| 42 | // GetTime returns the current Time (100s of nanoseconds since 15 Oct 1582) and |
| 43 | // clock sequence as well as adjusting the clock sequence as needed. An error |
| 44 | // is returned if the current time cannot be determined. |
| 45 | func GetTime() (Time, uint16, error) { |
| 46 | defer timeMu.Unlock() |
| 47 | timeMu.Lock() |
| 48 | return getTime() |
| 49 | } |
| 50 | |
| 51 | func getTime() (Time, uint16, error) { |
| 52 | t := timeNow() |
| 53 | |
| 54 | // If we don't have a clock sequence already, set one. |
| 55 | if clock_seq == 0 { |
| 56 | setClockSequence(-1) |
| 57 | } |
| 58 | now := uint64(t.UnixNano()/100) + g1582ns100 |
| 59 | |
| 60 | // If time has gone backwards with this clock sequence then we |
| 61 | // increment the clock sequence |
| 62 | if now <= lasttime { |
| 63 | clock_seq = ((clock_seq + 1) & 0x3fff) | 0x8000 |
| 64 | } |
| 65 | lasttime = now |
| 66 | return Time(now), clock_seq, nil |
| 67 | } |
| 68 | |
| 69 | // ClockSequence returns the current clock sequence, generating one if not |
| 70 | // already set. The clock sequence is only used for Version 1 UUIDs. |
| 71 | // |
| 72 | // The uuid package does not use global static storage for the clock sequence or |
| 73 | // the last time a UUID was generated. Unless SetClockSequence a new random |
| 74 | // clock sequence is generated the first time a clock sequence is requested by |
| 75 | // ClockSequence, GetTime, or NewUUID. (section 4.2.1.1) sequence is generated |
| 76 | // for |
| 77 | func ClockSequence() int { |
| 78 | defer timeMu.Unlock() |
| 79 | timeMu.Lock() |
| 80 | return clockSequence() |
| 81 | } |
| 82 | |
| 83 | func clockSequence() int { |
| 84 | if clock_seq == 0 { |
| 85 | setClockSequence(-1) |
| 86 | } |
| 87 | return int(clock_seq & 0x3fff) |
| 88 | } |
| 89 | |
| 90 | // SetClockSeq sets the clock sequence to the lower 14 bits of seq. Setting to |
| 91 | // -1 causes a new sequence to be generated. |
| 92 | func SetClockSequence(seq int) { |
| 93 | defer timeMu.Unlock() |
| 94 | timeMu.Lock() |
| 95 | setClockSequence(seq) |
| 96 | } |
| 97 | |
| 98 | func setClockSequence(seq int) { |
| 99 | if seq == -1 { |
| 100 | var b [2]byte |
| 101 | randomBits(b[:]) // clock sequence |
| 102 | seq = int(b[0])<<8 | int(b[1]) |
| 103 | } |
| 104 | old_seq := clock_seq |
| 105 | clock_seq = uint16(seq&0x3fff) | 0x8000 // Set our variant |
| 106 | if old_seq != clock_seq { |
| 107 | lasttime = 0 |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in |
| 112 | // uuid. It returns false if uuid is not valid. The time is only well defined |
| 113 | // for version 1 and 2 UUIDs. |
| 114 | func (uuid UUID) Time() (Time, bool) { |
| 115 | if len(uuid) != 16 { |
| 116 | return 0, false |
| 117 | } |
| 118 | time := int64(binary.BigEndian.Uint32(uuid[0:4])) |
| 119 | time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32 |
| 120 | time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48 |
| 121 | return Time(time), true |
| 122 | } |
| 123 | |
| 124 | // ClockSequence returns the clock sequence encoded in uuid. It returns false |
| 125 | // if uuid is not valid. The clock sequence is only well defined for version 1 |
| 126 | // and 2 UUIDs. |
| 127 | func (uuid UUID) ClockSequence() (int, bool) { |
| 128 | if len(uuid) != 16 { |
| 129 | return 0, false |
| 130 | } |
| 131 | return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff, true |
| 132 | } |