timeliness 0.3.2 → 0.3.3
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/CHANGELOG.rdoc +4 -0
- data/README.rdoc +11 -0
- data/Rakefile +0 -1
- data/benchmark.rb +18 -17
- data/lib/timeliness/core_ext.rb +6 -0
- data/lib/timeliness/core_ext/string.rb +22 -0
- data/lib/timeliness/definitions.rb +4 -2
- data/lib/timeliness/format.rb +2 -2
- data/lib/timeliness/format_set.rb +4 -1
- data/lib/timeliness/version.rb +1 -1
- data/spec/spec_helper.rb +1 -0
- data/spec/timeliness/core_ext/string_spec.rb +72 -0
- data/spec/timeliness/format_set_spec.rb +5 -0
- metadata +7 -6
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
= 0.3.3 - 2011-01-02
|
2
|
+
* Add String core extension for to_time, to_date and to_datetime methods, like ActiveSupport
|
3
|
+
* Allow arbitrary format string as :format option and it will be compiled, if not found.
|
4
|
+
|
1
5
|
= 0.3.2 - 2010-11-26
|
2
6
|
* Catch all errors for ActiveSupport not being loaded for more helpful error
|
3
7
|
|
data/README.rdoc
CHANGED
@@ -130,6 +130,17 @@ The last two value are the microseconds, and zone abbreviation or offset.
|
|
130
130
|
Note: The format for this value is not defined. You can add it yourself, easily.
|
131
131
|
|
132
132
|
|
133
|
+
=== ActiveSupport Core Extensions
|
134
|
+
|
135
|
+
To make it easier to use the parser in Rails or an app using ActiveSupport, you can add/override the methods
|
136
|
+
for <tt>to_time</tt>, <tt>to_date</tt> and <tt>to_datetime</tt> on a string value. These methods will then use
|
137
|
+
the Timeliness parser for converting a string, instead of the default.
|
138
|
+
|
139
|
+
You just need to add this line to an initializer or other application file:
|
140
|
+
|
141
|
+
require 'timeliness/core_ext'
|
142
|
+
|
143
|
+
|
133
144
|
== Formats
|
134
145
|
|
135
146
|
The gem has default formats included which can be easily added to using the format syntax. Also
|
data/Rakefile
CHANGED
data/benchmark.rb
CHANGED
@@ -2,18 +2,18 @@ $:.unshift(File.expand_path('lib'))
|
|
2
2
|
|
3
3
|
require 'benchmark'
|
4
4
|
require 'time'
|
5
|
-
require 'parsedate'
|
5
|
+
require 'parsedate' unless RUBY_VERSION =~ /^1\.9\./
|
6
6
|
require 'timeliness'
|
7
7
|
|
8
8
|
if defined?(JRUBY_VERSION)
|
9
9
|
# Warm up JRuby
|
10
|
-
|
10
|
+
20_000.times do
|
11
11
|
Time.parse("2000-01-04 12:12:12")
|
12
12
|
Timeliness::Parser.parse("2000-01-04 12:12:12", :datetime)
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
|
-
n =
|
16
|
+
n = 10_000
|
17
17
|
Benchmark.bm do |x|
|
18
18
|
x.report('timeliness - datetime') {
|
19
19
|
n.times do
|
@@ -102,8 +102,7 @@ Benchmark.bm do |x|
|
|
102
102
|
x.report('ISO regexp for datetime') {
|
103
103
|
n.times do
|
104
104
|
"2000-01-04 12:12:12" =~ /\A(\d{4})-(\d{2})-(\d{2}) (\d{2})[\. :](\d{2})([\. :](\d{2}))?\Z/
|
105
|
-
|
106
|
-
Time.mktime($1.to_i, $2.to_i, $3.to_i, $3.to_i, $5.to_i, $6.to_i, microsec)
|
105
|
+
Time.mktime($1.to_i, $2.to_i, $3.to_i, $3.to_i, $5.to_i, $6.to_i)
|
107
106
|
end
|
108
107
|
}
|
109
108
|
|
@@ -133,19 +132,21 @@ Benchmark.bm do |x|
|
|
133
132
|
end
|
134
133
|
}
|
135
134
|
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
135
|
+
if defined?(ParseDate)
|
136
|
+
x.report('parsedate - valid') {
|
137
|
+
n.times do
|
138
|
+
arr = ParseDate.parsedate("2000-01-04 12:12:12")
|
139
|
+
Date.new(*arr[0..2])
|
140
|
+
Time.mktime(*arr)
|
141
|
+
end
|
142
|
+
}
|
143
143
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
144
|
+
x.report('parsedate - invalid ') {
|
145
|
+
n.times do
|
146
|
+
arr = ParseDate.parsedate("2000-00-04 12:12:12")
|
147
|
+
end
|
148
|
+
}
|
149
|
+
end
|
149
150
|
|
150
151
|
x.report('strptime - valid') {
|
151
152
|
n.times do
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class String
|
2
|
+
|
3
|
+
# Form can be either :utc (default) or :local.
|
4
|
+
def to_time(form = :utc)
|
5
|
+
return nil if self.blank?
|
6
|
+
Timeliness::Parser.parse(self, :datetime, :zone => form)
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_date
|
10
|
+
return nil if self.blank?
|
11
|
+
values = Timeliness::Parser._parse(self, :date).map { |arg| arg || 0 }
|
12
|
+
::Date.new(*values[0..2])
|
13
|
+
end
|
14
|
+
|
15
|
+
def to_datetime
|
16
|
+
return nil if self.blank?
|
17
|
+
values = Timeliness::Parser._parse(self, :datetime).map { |arg| arg || 0 }
|
18
|
+
values[7] = values[7]/24.hours.to_f if values[7] != 0
|
19
|
+
values[5] += Rational(values.delete_at(6), 1000000)
|
20
|
+
::DateTime.civil(*values)
|
21
|
+
end
|
22
|
+
end
|
@@ -76,14 +76,16 @@ module Timeliness
|
|
76
76
|
'ddd, dd mmm yyyy hh:nn:ss zo', # RFC 822
|
77
77
|
'ddd mmm d hh:nn:ss zo yyyy', # Ruby time string
|
78
78
|
'yyyy-mm-ddThh:nn:ssZ', # ISO 8601 without zone offset
|
79
|
-
'yyyy-mm-ddThh:nn:sszo' # ISO 8601 with zone offset
|
79
|
+
'yyyy-mm-ddThh:nn:sszo', # ISO 8601 with zone offset
|
80
|
+
'yyyy-mm-ddThh:nn:ss.u', # ISO 8601 with usec
|
81
|
+
'yyyy-mm-ddThh:nn:ss.uzo' # ISO 8601 with usec and offset
|
80
82
|
]
|
81
83
|
|
82
84
|
# All tokens available for format construction. The token array is made of
|
83
85
|
# regexp and key for format component mapping, if any.
|
84
86
|
#
|
85
87
|
@format_tokens = {
|
86
|
-
'ddd' => [ '\w{3,9}' ],
|
88
|
+
'ddd' => [ '\w{3,9}', :wday ],
|
87
89
|
'dd' => [ '\d{2}', :day ],
|
88
90
|
'd' => [ '\d{1,2}', :day ],
|
89
91
|
'mmm' => [ '\w{3,9}', :month ],
|
data/lib/timeliness/format.rb
CHANGED
@@ -38,8 +38,8 @@ module Timeliness
|
|
38
38
|
@regexp_string = format
|
39
39
|
@regexp = Regexp.new("^(#{format})$")
|
40
40
|
self
|
41
|
-
rescue
|
42
|
-
raise "The format '#{format_string}' failed to compile using regexp string #{format}."
|
41
|
+
rescue => ex
|
42
|
+
raise "The format '#{format_string}' failed to compile using regexp string #{format}. Error: #{ex.inspect}"
|
43
43
|
end
|
44
44
|
|
45
45
|
# Redefined on compile
|
@@ -28,7 +28,7 @@ module Timeliness
|
|
28
28
|
end
|
29
29
|
|
30
30
|
def match(string, format_string=nil)
|
31
|
-
format =
|
31
|
+
format = single_format(format_string) if format_string
|
32
32
|
match_regexp = format && format.regexp || @regexp
|
33
33
|
|
34
34
|
if match_data = match_regexp.match(string)
|
@@ -40,5 +40,8 @@ module Timeliness
|
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
43
|
+
def single_format(format_string)
|
44
|
+
@formats_hash[format_string] || Format.new(format_string).compile!
|
45
|
+
end
|
43
46
|
end
|
44
47
|
end
|
data/lib/timeliness/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Timeliness::CoreExt, 'String' do
|
4
|
+
# Test values taken from ActiveSupport unit tests for compatibility
|
5
|
+
|
6
|
+
describe "#to_time" do
|
7
|
+
it 'should convert valid string to Time object in default zone' do
|
8
|
+
"2005-02-27 23:50".to_time.should == Time.utc(2005, 2, 27, 23, 50)
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'should convert ISO 8601 string to Time object' do
|
12
|
+
"2005-02-27T23:50:19.275038".to_time.should == Time.utc(2005, 2, 27, 23, 50, 19, 275038)
|
13
|
+
end
|
14
|
+
|
15
|
+
context "with :local" do
|
16
|
+
it 'should convert valid string to local time' do
|
17
|
+
"2005-02-27 23:50".to_time(:local).should == Time.local(2005, 2, 27, 23, 50)
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'should convert ISO 8601 string to local time' do
|
21
|
+
"2005-02-27T23:50:19.275038".to_time(:local).should == Time.local(2005, 2, 27, 23, 50, 19, 275038)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
it 'should convert valid future string to Time object' do
|
26
|
+
"2039-02-27 23:50".to_time(:local).should == Time.local_time(2039, 2, 27, 23, 50)
|
27
|
+
end
|
28
|
+
|
29
|
+
it 'should convert valid future string to Time object' do
|
30
|
+
"2039-02-27 23:50".to_time.should == DateTime.civil(2039, 2, 27, 23, 50)
|
31
|
+
end
|
32
|
+
|
33
|
+
it 'should convert empty string to nil' do
|
34
|
+
''.to_time.should be_nil
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#to_datetime" do
|
39
|
+
it 'should convert valid string to DateTime object' do
|
40
|
+
"2039-02-27 23:50".to_datetime.should == DateTime.civil(2039, 2, 27, 23, 50)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'should convert to DateTime object with UTC offset' do
|
44
|
+
"2039-02-27 23:50".to_datetime.offset.should == 0
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'should convert ISO 8601 string to DateTime object' do
|
48
|
+
datetime = DateTime.civil(2039, 2, 27, 23, 50, 19 + Rational(275038, 1000000), "-04:00")
|
49
|
+
"2039-02-27T23:50:19.275038-04:00".to_datetime.should == datetime
|
50
|
+
end
|
51
|
+
|
52
|
+
it 'should use Rubys default start value' do
|
53
|
+
# Taken from ActiveSupport unit tests. Not sure on the implication.
|
54
|
+
"2039-02-27 23:50".to_datetime.start.should == ::Date::ITALY
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should convert empty string to nil' do
|
58
|
+
''.to_datetime.should be_nil
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe "#to_date" do
|
63
|
+
it 'should convert string to Date object' do
|
64
|
+
"2005-02-27".to_date.should == Date.new(2005, 2, 27)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'should convert empty string to nil' do
|
68
|
+
''.to_date.should be_nil
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -88,6 +88,11 @@ describe Timeliness::FormatSet do
|
|
88
88
|
set.match('2000-01-02', 'yyyy-mm-dd').should be_kind_of(Array)
|
89
89
|
set.match('2000-01-02', 'dd/mm/yyyy').should be_nil
|
90
90
|
end
|
91
|
+
|
92
|
+
it 'should compile unknown format for one off match' do
|
93
|
+
set.match('20001011').should be_nil
|
94
|
+
set.match('20001011', 'yyyymmdd').should be_kind_of(Array)
|
95
|
+
end
|
91
96
|
end
|
92
97
|
|
93
98
|
def compile_regexp(format)
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timeliness
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash: 23
|
5
4
|
prerelease: false
|
6
5
|
segments:
|
7
6
|
- 0
|
8
7
|
- 3
|
9
|
-
-
|
10
|
-
version: 0.3.
|
8
|
+
- 3
|
9
|
+
version: 0.3.3
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Adam Meehan
|
@@ -15,7 +14,7 @@ autorequire:
|
|
15
14
|
bindir: bin
|
16
15
|
cert_chain: []
|
17
16
|
|
18
|
-
date:
|
17
|
+
date: 2011-01-02 00:00:00 +11:00
|
19
18
|
default_executable:
|
20
19
|
dependencies: []
|
21
20
|
|
@@ -37,6 +36,8 @@ files:
|
|
37
36
|
- Rakefile
|
38
37
|
- benchmark.rb
|
39
38
|
- lib/timeliness.rb
|
39
|
+
- lib/timeliness/core_ext.rb
|
40
|
+
- lib/timeliness/core_ext/string.rb
|
40
41
|
- lib/timeliness/definitions.rb
|
41
42
|
- lib/timeliness/format.rb
|
42
43
|
- lib/timeliness/format_set.rb
|
@@ -44,6 +45,7 @@ files:
|
|
44
45
|
- lib/timeliness/parser.rb
|
45
46
|
- lib/timeliness/version.rb
|
46
47
|
- spec/spec_helper.rb
|
48
|
+
- spec/timeliness/core_ext/string_spec.rb
|
47
49
|
- spec/timeliness/definitions_spec.rb
|
48
50
|
- spec/timeliness/format_set_spec.rb
|
49
51
|
- spec/timeliness/format_spec.rb
|
@@ -63,7 +65,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
63
65
|
requirements:
|
64
66
|
- - ">="
|
65
67
|
- !ruby/object:Gem::Version
|
66
|
-
hash: 3
|
67
68
|
segments:
|
68
69
|
- 0
|
69
70
|
version: "0"
|
@@ -72,7 +73,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
73
|
requirements:
|
73
74
|
- - ">="
|
74
75
|
- !ruby/object:Gem::Version
|
75
|
-
hash: 3
|
76
76
|
segments:
|
77
77
|
- 0
|
78
78
|
version: "0"
|
@@ -85,6 +85,7 @@ specification_version: 3
|
|
85
85
|
summary: Date/time parsing for the control freak.
|
86
86
|
test_files:
|
87
87
|
- spec/spec_helper.rb
|
88
|
+
- spec/timeliness/core_ext/string_spec.rb
|
88
89
|
- spec/timeliness/definitions_spec.rb
|
89
90
|
- spec/timeliness/format_set_spec.rb
|
90
91
|
- spec/timeliness/format_spec.rb
|