Rainbond/vendor/github.com/twinj/uuid/timestamp.go
2017-11-07 11:40:44 +08:00

118 lines
3.7 KiB
Go

package uuid
import (
"time"
)
const (
gregorianToUNIXOffset = 122192928e9
// set the following to the number of 100ns ticks of the actual
// resolution of your system's clock
defaultSpinResolution = 1024
)
// 4.1.4. Timestamp https://www.ietf.org/rfc/rfc4122.txt
//
// The timestamp is a 60-bit value. For UUID version 1, this is
//
// represented by Coordinated Universal Time (UTC) as a count of 100-
// nanosecond intervals since 00:00:00.00, 15 October 1582 (the date of
// Gregorian reform to the Christian calendar).
//
// For systems that do not have UTC available, but do have the local
// time, they may use that instead of UTC, as long as they do so
// consistently throughout the system. However, this is not recommended
// since generating the UTC from local time only needs a time zone
// offset.
//
// For UUID version 3 or 5, the timestamp is a 60-bit value constructed
// from a name as described in Section 4.3.
//
// For UUID version 4, the timestamp is a randomly or pseudo-randomly
// generated 60-bit value, as described in Section 4.4.
type Timestamp uint64
// Converts Unix formatted time to RFC4122 UUID formatted times
// UUID UTC base time is October 15, 1582.
// Unix base time is January 1, 1970.
// Converts time to 100 nanosecond ticks since epoch. Uses time.Now
func Now() Timestamp {
return Timestamp(time.Now().UnixNano()/100 + gregorianToUNIXOffset)
}
// Converts UUID Timestamp to UTC time.Time
// Note some higher clock resolutions will lose accuracy if above 100 ns ticks
func (o Timestamp) Time() time.Time {
return time.Unix(0, int64((o-gregorianToUNIXOffset)*100)).UTC()
}
// Returns the timestamp as modified by the duration
func (o Timestamp) Add(pDuration time.Duration) Timestamp {
return o + Timestamp(pDuration/100)
}
// Returns the timestamp as modified by the duration
func (o Timestamp) Sub(pDuration time.Duration) Timestamp {
return o - Timestamp(pDuration/100)
}
// Converts UUID Timestamp to time.Time and then calls the Stringer
func (o Timestamp) String() string {
return o.Time().String()
}
// 4.2.1.2. System Clock Resolution https://www.ietf.org/rfc/rfc4122.txt
//
// The timestamp is generated from the system time, whose resolution may
// be less than the resolution of the UUID timestamp.
//
// If UUIDs do not need to be frequently generated, the timestamp can
// simply be the system time multiplied by the number of 100-nanosecond
// intervals per system time interval.
//
// If a system overruns the generator by requesting too many UUIDs
// within a single system time interval, the UUID service MUST either
// return an error, or stall the UUID generator until the system clock
// catches up.
//
// A high resolution timestamp can be simulated by keeping a count of
// the number of UUIDs that have been generated with the same value of
// the system time, and using it to construct the low order bits of the
// timestamp. The count will range between zero and the number of
// 100-nanosecond intervals per system time interval.
//
// Note: If the processors overrun the UUID generation frequently,
// additional node identifiers can be allocated to the system, which
// will permit higher speed allocation by making multiple UUIDs
// potentially available for each time stamp value.
type spinner struct {
// the amount of ids based on the Timestamp
Count, Resolution uint
// the tracked spin stamp
Timestamp
}
func (o *spinner) next() Timestamp {
for {
now := Now()
// if clock reading changed since last UUID generated
if o.Timestamp == now {
o.Count++
if o.Count == o.Resolution {
for Now() < o.Timestamp+Timestamp(o.Resolution) {
}
continue
}
break
}
// reset count of UUIDs with this timestamp
o.Count = 0
o.Timestamp = now
break
}
return o.Timestamp + Timestamp(o.Count)
}