partial-date 1.1.9 → 1.1.10
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/.gitignore +1 -0
- data/ChangeLog.markdown +4 -0
- data/Rakefile +7 -0
- data/benchmarks/run-benchmarks.rb +78 -0
- data/benchmarks/run-gcprof.rb +52 -0
- data/benchmarks/run-perftools.rb +46 -0
- data/lib/partial-date/date.rb +38 -7
- data/lib/partial-date/version.rb +1 -1
- data/spec/to_s_spec.rb +35 -0
- metadata +7 -2
data/.gitignore
CHANGED
data/ChangeLog.markdown
CHANGED
data/Rakefile
CHANGED
@@ -3,6 +3,13 @@
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'rake'
|
5
5
|
|
6
|
+
# Benchmark setup inspired by https://github.com/stonean/slim
|
7
|
+
# Call 'rake benchmark iterations=10000' to set iterations
|
8
|
+
desc 'Run PartialDate benchmarks (default iterations=1000)'
|
9
|
+
task :benchmark, :iterations do
|
10
|
+
ruby('benchmarks/run-benchmarks.rb')
|
11
|
+
end
|
12
|
+
|
6
13
|
begin
|
7
14
|
gem 'rubygems-tasks', '~> 0.2'
|
8
15
|
require 'rubygems/tasks'
|
@@ -0,0 +1,78 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'partial-date'
|
6
|
+
require 'benchmark'
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
class PartialDateBenchmarks
|
10
|
+
def initialize(iterations)
|
11
|
+
@iterations = (iterations || 10000).to_i
|
12
|
+
@benches = []
|
13
|
+
|
14
|
+
stdlib_date = Date.new(2012,12,1)
|
15
|
+
partial_date = PartialDate::Date.new {|d| d.year = 2012; d.month = 12; d.day = 1}
|
16
|
+
|
17
|
+
bench('(1a) create empty stdlib date objects') do |d|
|
18
|
+
Date.new
|
19
|
+
end
|
20
|
+
|
21
|
+
bench('(1b) create empty partial-date objects') do |d|
|
22
|
+
PartialDate::Date.new
|
23
|
+
end
|
24
|
+
|
25
|
+
bench('(2a) create populated stdlib date objects') do |d|
|
26
|
+
Date.new(2012,12,1)
|
27
|
+
end
|
28
|
+
|
29
|
+
bench('(2b) create populated partial-date objects from block') do |d|
|
30
|
+
PartialDate::Date.new { |d| d.year = 2012; d.month = 12; d.day = 1 }
|
31
|
+
end
|
32
|
+
|
33
|
+
bench('(3) create partial-date objects from load method') do |d|
|
34
|
+
PartialDate::Date.load 20121201
|
35
|
+
end
|
36
|
+
|
37
|
+
bench('(4a) read stdlib date parts') do |d|
|
38
|
+
stdlib_date.year
|
39
|
+
stdlib_date.month
|
40
|
+
stdlib_date.day
|
41
|
+
end
|
42
|
+
|
43
|
+
bench('(4b) read partial-date date parts') do |d|
|
44
|
+
partial_date.year
|
45
|
+
partial_date.month
|
46
|
+
partial_date.day
|
47
|
+
end
|
48
|
+
|
49
|
+
bench('(5a) call stdlib date strftime') do |d|
|
50
|
+
stdlib_date.strftime('%Y-%m-%d')
|
51
|
+
end
|
52
|
+
|
53
|
+
bench('(5b) call partial-date to_s') do |d|
|
54
|
+
partial_date.to_s
|
55
|
+
end
|
56
|
+
|
57
|
+
bench('(5c) call partial-date old to_s') do |d|
|
58
|
+
partial_date.old_to_s
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def run
|
63
|
+
puts "#{@iterations} Iterations"
|
64
|
+
Benchmark.bmbm do |x|
|
65
|
+
@benches.each do |name, block|
|
66
|
+
x.report name.to_s do
|
67
|
+
@iterations.to_i.times { block.call }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def bench(name, &block)
|
74
|
+
@benches.push([name, block])
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
PartialDateBenchmarks.new(ENV['iterations']).run
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'partial-date'
|
6
|
+
require 'date'
|
7
|
+
|
8
|
+
|
9
|
+
class PartialDateMemoryProfile
|
10
|
+
def initialize(iterations)
|
11
|
+
@tmp_dir = File.expand_path('../tmp', __FILE__)
|
12
|
+
Dir.mkdir @tmp_dir unless Dir.exists? @tmp_dir
|
13
|
+
|
14
|
+
@iterations = (iterations || 100000).to_i
|
15
|
+
@profiles = []
|
16
|
+
@memory = []
|
17
|
+
|
18
|
+
# profile('create_stdlib_date') do |d|
|
19
|
+
# @memory << Date.new(2012,12,1)
|
20
|
+
# end
|
21
|
+
|
22
|
+
profile('create_partial_date') do |d|
|
23
|
+
@memory << PartialDate::Date.new { |d| d.year - 2012; d.month = 12; d.day = 1}
|
24
|
+
end
|
25
|
+
|
26
|
+
# profile('load_partial_date') do |d|
|
27
|
+
# PartialDate::Date.load(20121201)
|
28
|
+
# end
|
29
|
+
end
|
30
|
+
|
31
|
+
def run
|
32
|
+
puts "#{@iterations} Iterations"
|
33
|
+
GC::Profiler.enable()
|
34
|
+
@profiles.each do |name, block|
|
35
|
+
count = 1
|
36
|
+
@iterations.times do
|
37
|
+
block.call
|
38
|
+
if count % 1000 == 0
|
39
|
+
puts " GC Profile Report #{ count.to_s.rjust(5, '0') } for #{ name } and #{ @memory.length} objects."
|
40
|
+
puts GC::Profiler.report()
|
41
|
+
end
|
42
|
+
count += 1
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def profile(name, &block)
|
48
|
+
@profiles.push([@tmp_dir + "/" + name, block])
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
PartialDateMemoryProfile.new(ENV['iterations']).run
|
@@ -0,0 +1,46 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'), File.dirname(__FILE__))
|
4
|
+
|
5
|
+
require 'perftools'
|
6
|
+
require 'partial-date'
|
7
|
+
require 'date'
|
8
|
+
|
9
|
+
class PartialDateCPUProfile
|
10
|
+
def initialize(iterations)
|
11
|
+
@tmp_dir = File.expand_path('../tmp', __FILE__)
|
12
|
+
Dir.mkdir @tmp_dir unless Dir.exists? @tmp_dir
|
13
|
+
|
14
|
+
@iterations = (iterations || 100000).to_i
|
15
|
+
@profiles = []
|
16
|
+
|
17
|
+
profile('create_stdlib_date') do |d|
|
18
|
+
Date.new(2012,12,1)
|
19
|
+
end
|
20
|
+
|
21
|
+
profile('create_partial_date') do |d|
|
22
|
+
PartialDate::Date.new { |d| d.year - 2012; d.month = 12; d.day = 1}
|
23
|
+
end
|
24
|
+
|
25
|
+
profile('load_partial_date') do |d|
|
26
|
+
PartialDate::Date.load(20121201)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def run
|
31
|
+
puts "#{@iterations} Iterations"
|
32
|
+
@profiles.each do |name, block|
|
33
|
+
PerfTools::CpuProfiler.start(name) do
|
34
|
+
@iterations.times { block.call }
|
35
|
+
#@iterations.to_i.times { block.call }
|
36
|
+
end
|
37
|
+
system "pprof.rb --gif #{name} > #{name}.gif"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def profile(name, &block)
|
42
|
+
@profiles.push([@tmp_dir + "/" + name, block])
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
PartialDateCPUProfile.new(ENV['iterations']).run
|
data/lib/partial-date/date.rb
CHANGED
@@ -22,6 +22,8 @@ module PartialDate
|
|
22
22
|
YEAR_SHIFT = 9
|
23
23
|
MONTH_SHIFT = 5
|
24
24
|
|
25
|
+
REMOVALS = /[\/\,\-\s]/
|
26
|
+
|
25
27
|
# TODO: Implement i18n support detecting whether a load path has been set or not
|
26
28
|
# and if not - setting it here to a default set of translations that match
|
27
29
|
# the generally available tranlsations for localizing dates.
|
@@ -145,7 +147,7 @@ module PartialDate
|
|
145
147
|
if value.is_a?(Integer) && (value >= -10485761231 && value <= 10485761231)
|
146
148
|
@bits = self.class.set_date(@bits, value)
|
147
149
|
else
|
148
|
-
|
150
|
+
raise PartialDateError, "Date value must be an integer betwen -10485761231 and 10485761231"
|
149
151
|
end
|
150
152
|
end
|
151
153
|
|
@@ -212,10 +214,10 @@ module PartialDate
|
|
212
214
|
# Public: Set the day portion of a partial date. Day is optional so zero,
|
213
215
|
# nil and empty strings are allowed.
|
214
216
|
def day=(value)
|
215
|
-
raise DayError, "A month must be set before a day" if month == 0
|
216
|
-
|
217
217
|
value = 0 if value.nil?
|
218
218
|
|
219
|
+
raise DayError, "A month must be set before a day" if month == 0 && value !=0
|
220
|
+
|
219
221
|
if value.is_a?(String)
|
220
222
|
if value =~ /\A\d{1,2}\z/
|
221
223
|
value = value.to_i
|
@@ -246,8 +248,8 @@ module PartialDate
|
|
246
248
|
# %Y - Year with century (can be negative, 4 digits at least)
|
247
249
|
# -0001, 0000, 1995, 2009, 14292, etc.
|
248
250
|
# %m - Month of the year, zero-padded (01..12)
|
249
|
-
# %B - The full month name (
|
250
|
-
# %b - The abbreviated month name (
|
251
|
+
# %B - The full month name ('January')
|
252
|
+
# %b - The abbreviated month name ('Jan')
|
251
253
|
# %d - Day of the month, zero-padded (01..31)
|
252
254
|
# %e - Day of the month, blank-padded ( 1..31)
|
253
255
|
#
|
@@ -261,6 +263,35 @@ module PartialDate
|
|
261
263
|
def to_s(format = :default)
|
262
264
|
format = FORMATS[format] if format.is_a?(Symbol)
|
263
265
|
|
266
|
+
s = format.dup
|
267
|
+
|
268
|
+
n = b = 0
|
269
|
+
a = 1
|
270
|
+
while n < s.length
|
271
|
+
if s[n] == "%"
|
272
|
+
t = FORMAT_METHODS[s[n..n+1]].call( self )
|
273
|
+
if t.length == 0
|
274
|
+
if n >= 0 && n < s.length - 2
|
275
|
+
a = a + 1 if s[n+2] =~ REMOVALS
|
276
|
+
else
|
277
|
+
b = n - 1 if s[n-1] =~ REMOVALS
|
278
|
+
end
|
279
|
+
end
|
280
|
+
s.slice!(b..n+a)
|
281
|
+
s.insert(b, t)
|
282
|
+
n = b = b + t.length
|
283
|
+
a = 1
|
284
|
+
else
|
285
|
+
n = b += 1
|
286
|
+
end
|
287
|
+
end
|
288
|
+
s
|
289
|
+
end
|
290
|
+
|
291
|
+
# Here for the moment for benchmark comparisons
|
292
|
+
def old_to_s(format = :default)
|
293
|
+
format = FORMATS[format] if format.is_a?(Symbol)
|
294
|
+
|
264
295
|
result = format.dup
|
265
296
|
FORMAT_METHODS.each_pair do |key, value|
|
266
297
|
result.gsub!( key, value.call( self )) if result.include? key
|
@@ -272,9 +303,9 @@ module PartialDate
|
|
272
303
|
# Remove any trailing "/-," chars.
|
273
304
|
# Anything else - you're on your own ;-)
|
274
305
|
lead_trim = (year != 0 && format.lstrip.start_with?("%Y")) ? /\A[\/\,\s]+/ : /\A[\/\,\-\s]+/
|
275
|
-
|
306
|
+
result = result.gsub(lead_trim, '').gsub(/\s\s/, ' ').gsub(/[\/\-\,]([\/\-\,])/, '\1').gsub(/[\/\,\-\s]+\z/, '')
|
276
307
|
end
|
277
|
-
|
308
|
+
|
278
309
|
# Public: Spaceship operator for date comparisons. Comparisons
|
279
310
|
# are made by cascading down from year, to month to day. This
|
280
311
|
# should be faster than passing to self.value <=> other_date.value
|
data/lib/partial-date/version.rb
CHANGED
data/spec/to_s_spec.rb
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'partial-date'
|
3
|
+
|
4
|
+
describe PartialDate::Date do
|
5
|
+
|
6
|
+
let(:date) { PartialDate::Date.new }
|
7
|
+
|
8
|
+
describe "to string" do
|
9
|
+
it "should be fast" do
|
10
|
+
date.year = 2012; date.month = 12; date.day = 1
|
11
|
+
puts date.to_s
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should not have a dash at the end if day is missing" do
|
15
|
+
date.year = 2012; date.month = 12; date.day = 0
|
16
|
+
puts date.to_s
|
17
|
+
end
|
18
|
+
|
19
|
+
it "it should not have a trailing dash if month and day are missing" do
|
20
|
+
date.year = 2012; date.month = 0; date.day = 0
|
21
|
+
puts date.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
it "it should not have a leading dash if year is missing" do
|
25
|
+
date.year = 0; date.month = 12; date.day = 1
|
26
|
+
puts date.to_s
|
27
|
+
end
|
28
|
+
|
29
|
+
it "it should preserve the minus sign if year is negative" do
|
30
|
+
date.year = -1000; date.month = 12; date.day = 1
|
31
|
+
puts date.to_s
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: partial-date
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.10
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-05-
|
12
|
+
date: 2012-05-31 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rubygems-tasks
|
@@ -77,6 +77,9 @@ files:
|
|
77
77
|
- LICENSE.txt
|
78
78
|
- README.markdown
|
79
79
|
- Rakefile
|
80
|
+
- benchmarks/run-benchmarks.rb
|
81
|
+
- benchmarks/run-gcprof.rb
|
82
|
+
- benchmarks/run-perftools.rb
|
80
83
|
- lib/partial-date.rb
|
81
84
|
- lib/partial-date/date.rb
|
82
85
|
- lib/partial-date/error.rb
|
@@ -84,6 +87,7 @@ files:
|
|
84
87
|
- partial-date.gemspec
|
85
88
|
- spec/date_spec.rb
|
86
89
|
- spec/spec_helper.rb
|
90
|
+
- spec/to_s_spec.rb
|
87
91
|
homepage: https://github.com/58bits/partial-date#readme
|
88
92
|
licenses:
|
89
93
|
- MIT
|
@@ -113,3 +117,4 @@ summary: A simple date class that can be used to store partial date values in a
|
|
113
117
|
test_files:
|
114
118
|
- spec/date_spec.rb
|
115
119
|
- spec/spec_helper.rb
|
120
|
+
- spec/to_s_spec.rb
|