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 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
@@ -1,6 +1,5 @@
1
1
  require 'rubygems'
2
2
  require 'rake/rdoctask'
3
- require 'rubygems/specification'
4
3
  require 'rspec/core/rake_task'
5
4
 
6
5
  GEM_NAME = "timeliness"
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
- 20000.times do
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 = 10000
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
- microsec = ($7.to_f * 1_000_000).to_i
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
- 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
- }
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
- x.report('parsedate - invalid ') {
145
- n.times do
146
- arr = ParseDate.parsedate("2000-00-04 12:12:12")
147
- end
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,6 @@
1
+ require 'timeliness/core_ext/string'
2
+
3
+ module Timeliness
4
+ module CoreExt
5
+ end
6
+ end
@@ -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 ],
@@ -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 = @formats_hash[format_string] if format_string
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
@@ -1,3 +1,3 @@
1
1
  module Timeliness
2
- VERSION = '0.3.2'
2
+ VERSION = '0.3.3'
3
3
  end
data/spec/spec_helper.rb CHANGED
@@ -3,6 +3,7 @@ require 'rspec'
3
3
  require 'active_support/time'
4
4
  require 'timecop'
5
5
  require 'timeliness'
6
+ require 'timeliness/core_ext'
6
7
 
7
8
  module TimelinessHelpers
8
9
  def parser
@@ -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
- - 2
10
- version: 0.3.2
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: 2010-11-28 00:00:00 +11:00
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