druuid 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/druuid.rb +43 -0
- data/spec/druuid_spec.rb +57 -0
- metadata +80 -0
data/druuid.rb
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'securerandom'
|
2
|
+
|
3
|
+
# = Druuid
|
4
|
+
#
|
5
|
+
# Date-relative UUID generation.
|
6
|
+
module Druuid
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# The offset from which Druuid UUIDs are generated (in seconds).
|
11
|
+
attr_accessor :epoch
|
12
|
+
|
13
|
+
# Generates a time-sortable, 64-bit UUID.
|
14
|
+
#
|
15
|
+
# @example
|
16
|
+
# Druuid.gen
|
17
|
+
# # => 11142943683383068069
|
18
|
+
# @param [Time] time of UUID
|
19
|
+
# @param [Numeric] epoch offset
|
20
|
+
# @return [Bignum] UUID
|
21
|
+
def gen time = Time.now, epoch = epoch
|
22
|
+
ms = ((time.to_f - epoch.to_i) * 1e3).round
|
23
|
+
rand = (SecureRandom.random_number * 1e16).round
|
24
|
+
id = ms << (63 - 40)
|
25
|
+
id | rand % (2 ** (63 - 40))
|
26
|
+
end
|
27
|
+
|
28
|
+
# Determines when a given UUID was generated.
|
29
|
+
#
|
30
|
+
# @param [Numeric] uuid
|
31
|
+
# @param [Numeric] epoch offset
|
32
|
+
# @return [Time] when UUID was generated
|
33
|
+
# @example
|
34
|
+
# Druuid.time 11142943683383068069
|
35
|
+
# # => 2012-02-04 00:00:00 -0800
|
36
|
+
def time uuid, epoch = epoch
|
37
|
+
ms = uuid >> (63 - 40)
|
38
|
+
Time.at (ms / 1e3) + epoch.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
data/spec/druuid_spec.rb
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
require_relative '../druuid'
|
2
|
+
|
3
|
+
describe Druuid do
|
4
|
+
describe '.gen' do
|
5
|
+
it 'generates a UUID' do
|
6
|
+
uuid = Druuid.gen
|
7
|
+
uuid.should be_instance_of Bignum
|
8
|
+
uuid.should_not eq Druuid.gen
|
9
|
+
end
|
10
|
+
|
11
|
+
let(:datetime) { Time.utc 2012, 2, 4, 8 }
|
12
|
+
let(:prefix) { '111429436833' }
|
13
|
+
context 'with a given time' do
|
14
|
+
it 'generates the UUID against the time' do
|
15
|
+
Druuid.gen(datetime).to_s[0, 12].should eq prefix
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
let(:offset) { 60 * 60 * 24 }
|
20
|
+
context 'with a given epoch' do
|
21
|
+
it 'generates the UUID against the offset' do
|
22
|
+
Druuid.gen(datetime + offset, offset).to_s[0, 12].should eq prefix
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'with a default epoch' do
|
27
|
+
before { @old_epoch, Druuid.epoch = Druuid.epoch, offset }
|
28
|
+
it 'generates the UUID against the offset' do
|
29
|
+
Druuid.gen(datetime + offset).to_s[0, 12].should eq prefix
|
30
|
+
end
|
31
|
+
after { Druuid.epoch = @old_epoch }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe '.time' do
|
36
|
+
let(:datetime) { Time.utc 2012, 2, 4, 8 }
|
37
|
+
let(:uuid) { 11142943683383068069 }
|
38
|
+
it 'determines when a UUID was generated' do
|
39
|
+
Druuid.time(uuid).should eq datetime
|
40
|
+
end
|
41
|
+
|
42
|
+
let(:offset) { 60 * 60 * 24 }
|
43
|
+
context 'with a given epoch' do
|
44
|
+
it 'determines UUID date against the offset' do
|
45
|
+
Druuid.time(uuid, offset).should eq datetime + offset
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'with a default epoch' do
|
50
|
+
before { @old_epoch, Druuid.epoch = Druuid.epoch, offset }
|
51
|
+
it 'determines UUID date against the offest' do
|
52
|
+
Druuid.time(uuid).should eq datetime + offset
|
53
|
+
end
|
54
|
+
after { Druuid.epoch = @old_epoch }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
metadata
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: druuid
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Stephen Celis
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2013-02-05 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rake
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :development
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ! '>='
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rspec
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: Druuid generates 64-bit, time-sortable UUIDs.
|
47
|
+
email: stephen@recurly.com
|
48
|
+
executables: []
|
49
|
+
extensions: []
|
50
|
+
extra_rdoc_files: []
|
51
|
+
files:
|
52
|
+
- druuid.rb
|
53
|
+
- spec/druuid_spec.rb
|
54
|
+
homepage: https://github.com/recurly/druuid
|
55
|
+
licenses:
|
56
|
+
- MIT
|
57
|
+
post_install_message:
|
58
|
+
rdoc_options: []
|
59
|
+
require_paths:
|
60
|
+
- .
|
61
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '1.9'
|
67
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
requirements: []
|
74
|
+
rubyforge_project:
|
75
|
+
rubygems_version: 1.8.23
|
76
|
+
signing_key:
|
77
|
+
specification_version: 3
|
78
|
+
summary: Date-relative UUID generation
|
79
|
+
test_files:
|
80
|
+
- spec/druuid_spec.rb
|