Class: TimestampUuid

Inherits:
Object
  • Object
show all
Defined in:
lib/timestamp_uuid.rb,
lib/timestamp_uuid/version.rb

Overview

This is a UUID V4 compliant timestamp uuid with millisecond precision, for which also the string representation is correctly sorted by encoded timestamp (in contrast to time uuids used by e.g. cassandra)

Constant Summary collapse

MUTEX =
Mutex.new
VERSION =
"0.1.0"
@@sequence_number =
0

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(uuid) ⇒ TimestampUuid

Returns a new instance of TimestampUuid.



41
42
43
44
45
46
47
48
# File 'lib/timestamp_uuid.rb', line 41

def initialize(uuid)
  clean_uuid = uuid.gsub(/-/, "")

  @uuid = uuid
  @timestamp = Time.at("#{ clean_uuid[0, 12] }#{ clean_uuid[13, 2] }".to_i(16) / 1_000.0)
  @version = clean_uuid[12].to_i(16)
  @sequence_number = clean_uuid[15, 5].to_i(16)
end

Instance Attribute Details

#timestampObject (readonly)

Returns the value of attribute timestamp.



39
40
41
# File 'lib/timestamp_uuid.rb', line 39

def timestamp
  @timestamp
end

Class Method Details

.generate(timestamp = Time.now) ⇒ Object



14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/timestamp_uuid.rb', line 14

def self.generate(timestamp = Time.now)
  # The timestamp occupies 56 bit, such that it roughly works for the next 2
  # million years (from year 2022 on) with millisecond precision:
  #
  # ((Time.parse("2022-01-01") + 2_000_000.years).to_f * 1_000).to_i
  # => 63114068099520000
  # 16 ** 14
  # => 72057594037927936
  timestamp_part = "%014x" % (timestamp.to_f * 1_000).to_i

  # The sequence number takes 20 bit, such that roughly 1 million uuids could
  # be generated per millisecond max while having the correct sort order
  sequence_number_part = "%05x" % MUTEX.synchronize { @@sequence_number = (@@sequence_number + 1) % 1_048_575 }

  # The random part takes 48 bit
  random_part = SecureRandom.hex[0, 12]

  # The version takes 8 bit
  version_part = "4"

  hex = [timestamp_part, sequence_number_part, random_part].join.insert(12, version_part)

  [hex[0, 8], hex[8, 4], hex[12, 4], hex[16, 4], hex[20, 12]].join("-")
end

Instance Method Details

#to_sObject



50
51
52
# File 'lib/timestamp_uuid.rb', line 50

def to_s
  @uuid
end