go-duration 0.1.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ae1bf552d2be8eba1d80e8f4a1b8fe0f3a3438e6
4
+ data.tar.gz: f2d4b5986aba2578496e8beb0756a0d5db18f651
5
+ SHA512:
6
+ metadata.gz: 957897604363254f46829038ddb0592cf64d3c420bd4bef9509ce518ecfd072ea70d500f3c9974ab6f8d8e9213796860fe34eeb537b8466cfdd13c34e655d6d4
7
+ data.tar.gz: cb45a0f85333bf80c0476cbd57318b28b972e94516cde13ff0d3303922a913cc5508bad5bd62aa8b1d3429bd1674d981ba50798d39304272e708c329e9bfa655
@@ -0,0 +1,3 @@
1
+ require 'go-duration/version'
2
+ require 'go-duration/errors'
3
+ require 'go-duration/duration'
@@ -0,0 +1,131 @@
1
+ module GoDuration
2
+ # The base unit, a single nanosecond.
3
+ NANOSECOND = 1.freeze
4
+
5
+ # One microsecond in nanoseconds.
6
+ MICROSECOND = NANOSECOND << 10.freeze
7
+
8
+ # One millisecond in nanoseconds.
9
+ MILLISECOND = MICROSECOND << 1.freeze
10
+
11
+ # One second in nanoseconds.
12
+ SECOND = MILLISECOND << 1.freeze
13
+
14
+ # One minute in nanoseconds.
15
+ MINUTE = 60 * SECOND.freeze
16
+
17
+ # One hour in nanoseconds.
18
+ HOUR = 60 * MINUTE.freeze
19
+
20
+ # A mapping of Go's unit notations to their nanosecond values. Order is
21
+ # important, it defines how to_s works.
22
+ UNITS = {
23
+ h: HOUR,
24
+ m: MINUTE,
25
+ s: SECOND,
26
+ ms: MILLISECOND,
27
+ µs: MICROSECOND,
28
+ us: MICROSECOND,
29
+ ns: NANOSECOND,
30
+ }.freeze
31
+
32
+ # Duration deals with Golang's time.Duration. This type is commonly used
33
+ # in API's and/or CLI's, and is defined in the language itself (there is no
34
+ # formal specifcation or RFC for it). This class can be used to both parse
35
+ # and format duration strings.
36
+ class Duration
37
+ attr_reader :nanoseconds
38
+
39
+ # Initializes a new duration instance.
40
+ #
41
+ # @param number [Fixnum]
42
+ # @param unit [Symbol, :s]
43
+ #
44
+ # @return [Duration]
45
+ def initialize(number, unit: :s)
46
+ raise InvalidUnitError, unit unless UNITS[unit]
47
+ @nanoseconds = number * UNITS[unit]
48
+ end
49
+
50
+ # Returns the number of microseconds in the duration.
51
+ #
52
+ # @return [Fixnum]
53
+ def microseconds
54
+ nanoseconds / UNITS[:µs]
55
+ end
56
+
57
+ # Returns the number of milliseconds in the duration.
58
+ #
59
+ # @return [Fixnum]
60
+ def milliseconds
61
+ nanoseconds / UNITS[:ms]
62
+ end
63
+
64
+ # Returns the number of seconds in the duration.
65
+ #
66
+ # @return [Fixnum]
67
+ def seconds
68
+ nanoseconds / UNITS[:s]
69
+ end
70
+
71
+ # Returns the number of minutes in the duration.
72
+ #
73
+ # @return [Fixnum]
74
+ def minutes
75
+ nanoseconds / UNITS[:m]
76
+ end
77
+
78
+ # Returns the number of hours in the duration.
79
+ #
80
+ # @return [Fixnum]
81
+ def hours
82
+ nanoseconds / UNITS[:h]
83
+ end
84
+
85
+ # Returns the exact duration in nanoseconds.
86
+ #
87
+ # @return [Fixnum]
88
+ def to_i
89
+ nanoseconds
90
+ end
91
+
92
+ # Formats the duration into a Go duration string.
93
+ #
94
+ # @return [String]
95
+ def to_s
96
+ ns = nanoseconds
97
+ fmt = ""
98
+
99
+ UNITS.each do |unit, value|
100
+ number, ns = ns.divmod(value)
101
+ fmt << "#{number}#{unit}" if number > 0
102
+ end
103
+
104
+ fmt
105
+ end
106
+ end
107
+
108
+ module_function
109
+
110
+ # Parses a Go time.Duration string.
111
+ #
112
+ # @param duration [String] A Go duration string.
113
+ #
114
+ # @return [Duration]
115
+ def parse(duration)
116
+ ns = 0
117
+
118
+ until duration.empty?
119
+ number = duration.slice!(/^[[:digit:]]+/).to_i
120
+ unit = duration.slice!(/^[[:alpha:]]+/).to_sym
121
+
122
+ # Check that the units are recognized.
123
+ raise InvalidUnitError, unit unless UNITS[unit]
124
+
125
+ # Convert to nanoseconds and add to the total.
126
+ ns += (number * UNITS[unit])
127
+ end
128
+
129
+ Duration.new(ns, unit: :ns)
130
+ end
131
+ end
@@ -0,0 +1,11 @@
1
+ module GoDuration
2
+ class GoDurationError < RuntimeError; end
3
+
4
+ class InvalidUnitError < GoDurationError
5
+ def initialize(unit)
6
+ super <<-EOF.gsub(/^\s*/, "")
7
+ Invalid unit `#{unit}'. Must be one of: #{UNITS.keys.join(", ")}
8
+ EOF
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,3 @@
1
+ module GoDuration
2
+ VERSION = "0.1.3".freeze
3
+ end
@@ -0,0 +1,69 @@
1
+ require "spec_helper"
2
+
3
+ module GoDuration
4
+ all_duration = "1h1m1s1ms1µs1ns"
5
+ all_nano = HOUR + MINUTE + SECOND + MILLISECOND + MICROSECOND + NANOSECOND
6
+
7
+ describe Duration do
8
+ describe "#new" do
9
+ it "creates from seconds by default" do
10
+ d = Duration.new(13)
11
+ expect(d.nanoseconds).to eq(13 * GoDuration::SECOND)
12
+ end
13
+
14
+ it "creates with the provided unit" do
15
+ d = Duration.new(13, unit: :ms)
16
+ expect(d.nanoseconds).to eq(13 * GoDuration::MILLISECOND)
17
+ end
18
+
19
+ it "raises an error on invalid unit" do
20
+ expect { Duration.new(1, unit: :nope) }
21
+ .to raise_error(GoDuration::InvalidUnitError)
22
+ end
23
+ end
24
+
25
+ describe "#to_s" do
26
+ context "when all units are present" do
27
+ it "renders all of the units" do
28
+ expect(Duration.new(all_nano, unit: :ns).to_s)
29
+ .to eq(all_duration)
30
+ end
31
+ end
32
+
33
+ context "when a unit overflows" do
34
+ it "reduces into a larger unit" do
35
+ expect(Duration.new(63, unit: :s).to_s).to eq("1m3s")
36
+ end
37
+ end
38
+ end
39
+ end
40
+
41
+ describe "#parse" do
42
+ it "parses a time.Duration string" do
43
+ d = GoDuration.parse("1h")
44
+ expect(d.nanoseconds).to eq(HOUR)
45
+ end
46
+
47
+ it "recognizes either form of microseconds" do
48
+ a = GoDuration.parse("99us").microseconds
49
+ b = GoDuration.parse("99µs").microseconds
50
+ expect(a).to eq(b)
51
+ end
52
+
53
+ context "when multiple units are present" do
54
+ it "converts and adds them up" do
55
+ d = GoDuration.parse("1h43m")
56
+ expect(d.nanoseconds).to eq(HOUR + (43 * MINUTE))
57
+ end
58
+
59
+ it "recognizes all of the units" do
60
+ d = GoDuration.parse(all_duration)
61
+ expect(d.nanoseconds).to eq(all_nano)
62
+ end
63
+
64
+ it "raises an error if an invalid unit is found" do
65
+ expect { GoDuration.parse("1h2x") }.to raise_error(InvalidUnitError)
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1 @@
1
+ require 'go-duration'
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: go-duration
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.3
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Uber
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: yard
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ description: A parser and formatter for Golang's time.Duration
70
+ email:
71
+ - ru@ryanuber.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - lib/go-duration.rb
77
+ - lib/go-duration/duration.rb
78
+ - lib/go-duration/errors.rb
79
+ - lib/go-duration/version.rb
80
+ - spec/go-duration/duration_spec.rb
81
+ - spec/spec_helper.rb
82
+ homepage: https://github.com/ryanuber/go-duration-ruby
83
+ licenses:
84
+ - MIT
85
+ metadata: {}
86
+ post_install_message:
87
+ rdoc_options: []
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: '0'
95
+ required_rubygems_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ requirements: []
101
+ rubyforge_project:
102
+ rubygems_version: 2.5.1
103
+ signing_key:
104
+ specification_version: 4
105
+ summary: A parser and formatter for Golang's time.Duration
106
+ test_files:
107
+ - spec/spec_helper.rb
108
+ - spec/go-duration/duration_spec.rb