[822] | 1 | // Copyright 2016 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 | clockSeq 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 clockSeq == 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 | clockSeq = ((clockSeq + 1) & 0x3fff) | 0x8000
|
---|
| 64 | }
|
---|
| 65 | lasttime = now
|
---|
| 66 | return Time(now), clockSeq, 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 is used, a new
|
---|
| 74 | // random clock sequence is generated the first time a clock sequence is
|
---|
| 75 | // requested by ClockSequence, GetTime, or NewUUID. (section 4.2.1.1)
|
---|
| 76 | func ClockSequence() int {
|
---|
| 77 | defer timeMu.Unlock()
|
---|
| 78 | timeMu.Lock()
|
---|
| 79 | return clockSequence()
|
---|
| 80 | }
|
---|
| 81 |
|
---|
| 82 | func clockSequence() int {
|
---|
| 83 | if clockSeq == 0 {
|
---|
| 84 | setClockSequence(-1)
|
---|
| 85 | }
|
---|
| 86 | return int(clockSeq & 0x3fff)
|
---|
| 87 | }
|
---|
| 88 |
|
---|
| 89 | // SetClockSequence sets the clock sequence to the lower 14 bits of seq. Setting to
|
---|
| 90 | // -1 causes a new sequence to be generated.
|
---|
| 91 | func SetClockSequence(seq int) {
|
---|
| 92 | defer timeMu.Unlock()
|
---|
| 93 | timeMu.Lock()
|
---|
| 94 | setClockSequence(seq)
|
---|
| 95 | }
|
---|
| 96 |
|
---|
| 97 | func setClockSequence(seq int) {
|
---|
| 98 | if seq == -1 {
|
---|
| 99 | var b [2]byte
|
---|
| 100 | randomBits(b[:]) // clock sequence
|
---|
| 101 | seq = int(b[0])<<8 | int(b[1])
|
---|
| 102 | }
|
---|
| 103 | oldSeq := clockSeq
|
---|
| 104 | clockSeq = uint16(seq&0x3fff) | 0x8000 // Set our variant
|
---|
| 105 | if oldSeq != clockSeq {
|
---|
| 106 | lasttime = 0
|
---|
| 107 | }
|
---|
| 108 | }
|
---|
| 109 |
|
---|
| 110 | // Time returns the time in 100s of nanoseconds since 15 Oct 1582 encoded in
|
---|
| 111 | // uuid. The time is only defined for version 1 and 2 UUIDs.
|
---|
| 112 | func (uuid UUID) Time() Time {
|
---|
| 113 | time := int64(binary.BigEndian.Uint32(uuid[0:4]))
|
---|
| 114 | time |= int64(binary.BigEndian.Uint16(uuid[4:6])) << 32
|
---|
| 115 | time |= int64(binary.BigEndian.Uint16(uuid[6:8])&0xfff) << 48
|
---|
| 116 | return Time(time)
|
---|
| 117 | }
|
---|
| 118 |
|
---|
| 119 | // ClockSequence returns the clock sequence encoded in uuid.
|
---|
| 120 | // The clock sequence is only well defined for version 1 and 2 UUIDs.
|
---|
| 121 | func (uuid UUID) ClockSequence() int {
|
---|
| 122 | return int(binary.BigEndian.Uint16(uuid[8:10])) & 0x3fff
|
---|
| 123 | }
|
---|