partial-date 1.1.9 → 1.1.10
Sign up to get free protection for your applications and to get access to all the features.
- 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
|