timeliness 0.1.1 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.rdoc +7 -0
- data/README.rdoc +62 -39
- data/lib/timeliness.rb +10 -3
- data/lib/timeliness/format_set.rb +5 -1
- data/lib/timeliness/formats.rb +2 -1
- data/lib/timeliness/parser.rb +34 -21
- data/lib/timeliness/version.rb +1 -1
- data/spec/timeliness/format_set_spec.rb +10 -6
- data/spec/timeliness/formats_spec.rb +12 -11
- data/spec/timeliness/parser_spec.rb +42 -17
- data/timeliness.gemspec +2 -2
- metadata +5 -5
data/CHANGELOG.rdoc
CHANGED
@@ -1,3 +1,10 @@
|
|
1
|
+
= 0.2.0 - 2010-10-27
|
2
|
+
* Allow a lambda for date_for_time_type which is evaluated on parse
|
3
|
+
* Return the offset or zone in array from _parse
|
4
|
+
* Give a nicer error message if use a zone and ActiveSupport is not loaded.
|
5
|
+
* Removed some aliases used in validates_timeliness and are no longer needed.
|
6
|
+
* Some minor spec fixes
|
7
|
+
|
1
8
|
= 0.1.1 - 2010-10-14
|
2
9
|
* Alias for validates_timeliness compatibility
|
3
10
|
* Tiny cleanup
|
data/README.rdoc
CHANGED
@@ -14,9 +14,11 @@ Date/time parser for Ruby with the following features:
|
|
14
14
|
* I18n support (for months), if I18n gem loaded.
|
15
15
|
* Fewer WTFs than Time/Date parse method.
|
16
16
|
* Has no dependencies.
|
17
|
+
* Works with Ruby MRI 1.8.*, 1.9.2, Rubinius
|
17
18
|
|
18
19
|
Extracted from my {validates_timeliness gem}[http://github.com/adzap/validates_timeliness], it has been rewritten cleaner and much faster. It's most suitable for when
|
19
|
-
you need to control the parsing behaviour. It's faster than the Time/Date class parse methods, so it
|
20
|
+
you need to control the parsing behaviour. It's faster than the Time/Date class parse methods, so it
|
21
|
+
has general appeal.
|
20
22
|
|
21
23
|
|
22
24
|
== Usage
|
@@ -27,16 +29,11 @@ The simplest example is just a straight forward string parse:
|
|
27
29
|
Timeliness.parse('2010-09-08') #=> Wed Sep 08 00:00:00 1000 2010
|
28
30
|
Timeliness.parse('12:13:14') #=> Sat Jan 01 12:13:14 1100 2000
|
29
31
|
|
30
|
-
Notice a time only string will return with a date value. The date value can be configured globally with
|
31
|
-
this setting:
|
32
32
|
|
33
|
-
|
34
|
-
|
35
|
-
or specified with :now option:
|
33
|
+
=== Specify a Type
|
36
34
|
|
37
|
-
|
38
|
-
|
39
|
-
You can also provide a type which will tell the parser that you are only interested in the part of the value for that type.
|
35
|
+
You can provide a type which will tell the parser that you are only interested in the part of
|
36
|
+
the value for that type.
|
40
37
|
|
41
38
|
Timeliness.parse('2010-09-08 12:13:14', :date) #=> Wed Sep 08 00:00:00 1000 2010
|
42
39
|
Timeliness.parse('2010-09-08 12:13:14', :time) #=> Sat Jan 01 12:13:14 1100 2000
|
@@ -48,15 +45,35 @@ Now let's get strict. Pass the :strict option with true and things get finicky
|
|
48
45
|
Timeliness.parse('2010-09-08 12:13:14', :time, :strict => true) #=> nil
|
49
46
|
Timeliness.parse('2010-09-08 12:13:14', :datetime, :strict => true) #=> Wed Sep 08 12:13:14 1000 2010 i.e. the whole string is used
|
50
47
|
|
51
|
-
The date and time strings are not accepted for a datetime type. The strict option without a type is
|
48
|
+
The date and time strings are not accepted for a datetime type. The strict option without a type is
|
49
|
+
ignored.
|
50
|
+
|
51
|
+
|
52
|
+
=== Specify the Current Date
|
53
|
+
|
54
|
+
Notice a time only string will return with a date value. The date value can be configured globally
|
55
|
+
with this setting:
|
56
|
+
|
57
|
+
Timeliness.date_for_time_type = [2010, 1, 1]
|
58
|
+
|
59
|
+
or using a lambda thats evaluated when parsed
|
52
60
|
|
53
|
-
|
54
|
-
|
61
|
+
Timeliness.date_for_time_type = lambda { Time.now }
|
62
|
+
|
63
|
+
It can also be specified with :now option:
|
64
|
+
|
65
|
+
Timeliness.parse('12:13:14', :now => Time.mktime(2010,9,8)) #=> Wed Sep 08 12:13:14 1000 2010
|
66
|
+
|
67
|
+
|
68
|
+
=== Timezone
|
69
|
+
|
70
|
+
To control what zone the time object is returned in, you have two options. Firstly you can set the
|
71
|
+
default zone. Below is the list of options with their effective time creation method call
|
55
72
|
|
56
73
|
Timeliness.default_timezone = :local # Time.local(...)
|
57
74
|
Timeliness.default_timezone = :utc # Time.utc(...)
|
58
|
-
Timeliness.default_timezone = :current # Time.zone.local(...)
|
59
|
-
Timeliness.default_timezone = 'Melbourne' # Time.use_zone('Melbourne') { Time.zone.local(...) }
|
75
|
+
Timeliness.default_timezone = :current # Time.zone.local(...). Use current zone.
|
76
|
+
Timeliness.default_timezone = 'Melbourne' # Time.use_zone('Melbourne') { Time.zone.local(...) }. Doesn't change Time.zone.
|
60
77
|
|
61
78
|
The last two options require that you have ActiveSupport timezone extension loaded.
|
62
79
|
|
@@ -69,25 +86,32 @@ You can also use the :zone option to control it for a single parse call:
|
|
69
86
|
|
70
87
|
Remember, you must have ActiveSupport timezone extension loaded to use the last two examples.
|
71
88
|
|
89
|
+
|
90
|
+
=== Restrict to Format
|
91
|
+
|
72
92
|
To get super finicky, you can restrict the parsing to a single format with the :format option
|
73
93
|
|
74
94
|
Timeliness.parse('2010-09-08 12:13:14', :format => 'yyyy-mm-dd hh:nn:ss') #=> Wed Sep 08 12:13:14 UTC 2010
|
75
95
|
Timeliness.parse('08/09/2010 12:13:14', :format => 'yyyy-mm-dd hh:nn:ss') #=> nil
|
76
96
|
|
97
|
+
|
98
|
+
=== Raw Parsed Values
|
99
|
+
|
77
100
|
If you would like to get the raw array of values before the time object is created, you can with
|
78
101
|
|
79
|
-
Timeliness._parse('2010-09-08 12:13:14') # => [2010, 9, 8, 12, 13, 14, nil]
|
102
|
+
Timeliness._parse('2010-09-08 12:13:14') # => [2010, 9, 8, 12, 13, 14, nil, nil]
|
80
103
|
|
81
|
-
The last
|
104
|
+
The last two nils are for the empty value of microseconds, and timezone or offset.
|
82
105
|
|
83
106
|
|
84
107
|
== Formats
|
85
108
|
|
86
|
-
The gem has default formats included which can be easily added to using the format syntax. Also
|
87
|
-
removed so that they are no longer considered valid.
|
109
|
+
The gem has default formats included which can be easily added to using the format syntax. Also
|
110
|
+
formats can be easily removed so that they are no longer considered valid.
|
88
111
|
|
89
|
-
Below are the default formats. If you think they are easy to read then you will be happy to know
|
90
|
-
format syntax you can use to define your own. No complex regular
|
112
|
+
Below are the default formats. If you think they are easy to read then you will be happy to know
|
113
|
+
that is exactly the same format syntax you can use to define your own. No complex regular
|
114
|
+
expressions are needed.
|
91
115
|
|
92
116
|
|
93
117
|
=== Datetime formats
|
@@ -164,7 +188,8 @@ Here is what each format token means:
|
|
164
188
|
ddd = Day name of 3 to 9 letters (e.g. Wed or Wednesday)
|
165
189
|
u = microseconds matches 1 to 3 digits
|
166
190
|
|
167
|
-
All other characters are considered literal. For the technically minded, these formats are compiled
|
191
|
+
All other characters are considered literal. For the technically minded, these formats are compiled
|
192
|
+
into a single regular expression
|
168
193
|
|
169
194
|
To see all defined formats look at the {source code}[http://github.com/adzap/timeliness/tree/master/lib/timeliness/formats.rb].
|
170
195
|
|
@@ -173,9 +198,9 @@ To see all defined formats look at the {source code}[http://github.com/adzap/tim
|
|
173
198
|
|
174
199
|
=== US/Euro Formats
|
175
200
|
|
176
|
-
The perennial problem for non-US developers or applications not primarily for the
|
177
|
-
|
178
|
-
|
201
|
+
The perennial problem for non-US developers or applications not primarily for the US, is the US date
|
202
|
+
format of m/d/yy. This is ambiguous with the European format of d/m/yy. By default the gem uses the
|
203
|
+
US formats as this is the Ruby default
|
179
204
|
when it does date interpretation.
|
180
205
|
|
181
206
|
To switch to using the European (or Rest of The World) formats use this setting
|
@@ -191,8 +216,8 @@ You can switch back to US formats with
|
|
191
216
|
|
192
217
|
=== Customising Formats
|
193
218
|
|
194
|
-
Sometimes you may not want certain formats to be valid. You can remove formats for each type and
|
195
|
-
|
219
|
+
Sometimes you may not want certain formats to be valid. You can remove formats for each type and the
|
220
|
+
parser will then not consider that a valid format. To remove a format
|
196
221
|
|
197
222
|
Timeliness.remove_formats(:date, 'm\d\yy')
|
198
223
|
|
@@ -202,27 +227,25 @@ Adding new formats is also simple
|
|
202
227
|
|
203
228
|
Now "10 o'clock" will be a valid value.
|
204
229
|
|
205
|
-
You can embed regular expressions in the format but no guarantees that it will
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
datetime for an example of an embedded regular expression.
|
230
|
+
You can embed regular expressions in the format but no guarantees that it will remain intact. If
|
231
|
+
you avoid the use of any token characters, and regexp dots or backslashes as special characters in
|
232
|
+
the regexp, it may work as expected. For special characters use POSIX character classes for safety.
|
233
|
+
See the ISO 8601 datetime for an example of an embedded regular expression.
|
210
234
|
|
211
|
-
Because formats are evaluated in order, adding a format which may be ambiguous
|
212
|
-
|
213
|
-
|
214
|
-
before option like so
|
235
|
+
Because formats are evaluated in order, adding a format which may be ambiguous with an existing
|
236
|
+
format, will mean your format is ignored. If you need to make your new format higher precedence than
|
237
|
+
an existing format, you can include the before option like so
|
215
238
|
|
216
239
|
Timeliness.add_formats(:time, 'ss:nn:hh', :before => 'hh:nn:ss')
|
217
240
|
|
218
|
-
Now a time of '59:30:23' will be interpreted as 11:30:59 pm. This option saves
|
219
|
-
|
241
|
+
Now a time of '59:30:23' will be interpreted as 11:30:59 pm. This option saves you adding a new one
|
242
|
+
and deleting an old one to get it to work.
|
220
243
|
|
221
244
|
|
222
245
|
=== Ambiguous Year
|
223
246
|
|
224
|
-
When dealing with 2 digit year values, by default a year is interpreted as being
|
225
|
-
|
247
|
+
When dealing with 2 digit year values, by default a year is interpreted as being in the last century
|
248
|
+
when at or above 30. You can customize this however
|
226
249
|
|
227
250
|
Timeliness.ambiguous_year_threshold = 20
|
228
251
|
|
data/lib/timeliness.rb
CHANGED
@@ -12,10 +12,7 @@ module Timeliness
|
|
12
12
|
extend Forwardable
|
13
13
|
def_delegators Parser, :parse, :_parse
|
14
14
|
def_delegators Formats, :add_formats, :remove_formats, :use_us_formats, :use_euro_formats
|
15
|
-
|
16
15
|
attr_accessor :default_timezone, :date_for_time_type, :ambiguous_year_threshold
|
17
|
-
|
18
|
-
alias :dummy_date_for_time_type :date_for_time_type
|
19
16
|
end
|
20
17
|
|
21
18
|
# Default timezone. Options:
|
@@ -31,6 +28,16 @@ module Timeliness
|
|
31
28
|
# Set the default date part for a time type values.
|
32
29
|
@date_for_time_type = [ 2000, 1, 1 ]
|
33
30
|
|
31
|
+
def self.date_for_time_type
|
32
|
+
case @date_for_time_type
|
33
|
+
when Array
|
34
|
+
@date_for_time_type
|
35
|
+
when Proc
|
36
|
+
v = @date_for_time_type.call
|
37
|
+
[v.year, v.month, v.day]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
34
41
|
# Set the threshold value for a two digit year to be considered last century
|
35
42
|
#
|
36
43
|
# Default: 30
|
@@ -48,7 +48,7 @@ module Timeliness
|
|
48
48
|
# values placed in the position defined by the component.
|
49
49
|
#
|
50
50
|
def define_format_method(name, components)
|
51
|
-
values = [nil] *
|
51
|
+
values = [nil] * 8
|
52
52
|
components.each do |component|
|
53
53
|
position, code = *Formats.format_components[component]
|
54
54
|
values[position] = code || "#{component}.to_i" if position
|
@@ -66,6 +66,10 @@ module Timeliness
|
|
66
66
|
@formats = formats
|
67
67
|
end
|
68
68
|
|
69
|
+
# Compiles the formats into one big regexp. Stores the index of where
|
70
|
+
# each format's capture values begin in the match data. Each individual
|
71
|
+
# format regpexp is also stored for use with the parse :format option.
|
72
|
+
#
|
69
73
|
def compile!
|
70
74
|
regexp_string = ''
|
71
75
|
@format_regexps = {}
|
data/lib/timeliness/formats.rb
CHANGED
@@ -100,7 +100,7 @@ module Timeliness
|
|
100
100
|
'u' => [ '\d{1,6}', :usec ],
|
101
101
|
'ampm' => [ '[aApP]\.?[mM]\.?', :meridian ],
|
102
102
|
'zo' => [ '[+-]\d{2}:?\d{2}', :offset ],
|
103
|
-
'tz' => [ '[A-Z]{1,4}' ],
|
103
|
+
'tz' => [ '[A-Z]{1,4}', :zone ],
|
104
104
|
'_' => [ '\s?' ]
|
105
105
|
}
|
106
106
|
|
@@ -122,6 +122,7 @@ module Timeliness
|
|
122
122
|
:sec => [ 5 ],
|
123
123
|
:usec => [ 6, 'microseconds(usec)'],
|
124
124
|
:offset => [ 7, 'offset_in_seconds(offset)'],
|
125
|
+
:zone => [ 7, 'zone'],
|
125
126
|
:meridian => [ nil ]
|
126
127
|
}
|
127
128
|
|
data/lib/timeliness/parser.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
module Timeliness
|
2
2
|
module Parser
|
3
|
+
class MissingTimezoneSupport < StandardError; end
|
3
4
|
|
4
5
|
class << self
|
5
6
|
|
@@ -12,18 +13,11 @@ module Timeliness
|
|
12
13
|
time_array = _parse(value, type, options)
|
13
14
|
return nil if time_array.nil?
|
14
15
|
|
15
|
-
|
16
|
-
when :date
|
17
|
-
time_array[3..7] = nil
|
18
|
-
when :time
|
19
|
-
time_array[0..2] = current_date(options)
|
20
|
-
when nil
|
21
|
-
dummy_date = current_date(options)
|
22
|
-
time_array[0] ||= dummy_date[0]
|
23
|
-
time_array[1] ||= dummy_date[1]
|
24
|
-
time_array[2] ||= dummy_date[2]
|
25
|
-
end
|
16
|
+
override_values_by_type(time_array, type, options) unless type == :datetime
|
26
17
|
make_time(time_array[0..6], options[:zone])
|
18
|
+
rescue NoMethodError => ex
|
19
|
+
raise ex unless ex.message =~ /zone/
|
20
|
+
raise MissingTimezoneSupport, "ActiveSupport must be loaded to use timezones other than :utc and :local."
|
27
21
|
end
|
28
22
|
|
29
23
|
def make_time(time_array, zone=nil)
|
@@ -57,21 +51,40 @@ module Timeliness
|
|
57
51
|
|
58
52
|
private
|
59
53
|
|
54
|
+
def override_values_by_type(values, type, options)
|
55
|
+
case type
|
56
|
+
when :date
|
57
|
+
values[3..7] = nil
|
58
|
+
when :time
|
59
|
+
values[0..2] = current_date(options)
|
60
|
+
when nil
|
61
|
+
dummy_date = current_date(options)
|
62
|
+
values[0] ||= dummy_date[0]
|
63
|
+
values[1] ||= dummy_date[1]
|
64
|
+
values[2] ||= dummy_date[2]
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
60
68
|
def current_date(options)
|
61
69
|
now = if options[:now]
|
62
70
|
options[:now]
|
63
71
|
elsif options[:zone]
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
+
current_time_in_zone(options[:zone])
|
73
|
+
else
|
74
|
+
Timeliness.date_for_time_type
|
75
|
+
end
|
76
|
+
now.is_a?(Array) ? now[0..2] : [now.year, now.month, now.day]
|
77
|
+
end
|
78
|
+
|
79
|
+
def current_time_in_zone(zone)
|
80
|
+
case zone
|
81
|
+
when :utc, :local
|
82
|
+
Time.now.send("get#{zone}")
|
83
|
+
when :current
|
84
|
+
Time.current
|
85
|
+
else
|
86
|
+
Time.use_zone(zone) { Time.current }
|
72
87
|
end
|
73
|
-
now ||= Timeliness.date_for_time_type
|
74
|
-
now.is_a?(Array) ? now[0..2] : Array(now).reverse[4..6]
|
75
88
|
end
|
76
89
|
|
77
90
|
# Taken from ActiveSupport and simplified
|
data/lib/timeliness/version.rb
CHANGED
@@ -3,32 +3,36 @@ require 'spec_helper'
|
|
3
3
|
describe Timeliness::FormatSet do
|
4
4
|
context ".define_format_method" do
|
5
5
|
it "should define method which outputs date array with values in correct order" do
|
6
|
-
define_method_for('yyyy-mm-dd').call('2000', '1', '2').should == [2000,1,2,nil,nil,nil,nil]
|
6
|
+
define_method_for('yyyy-mm-dd').call('2000', '1', '2').should == [2000,1,2,nil,nil,nil,nil,nil]
|
7
7
|
end
|
8
8
|
|
9
9
|
it "should define method which outputs date array from format with different order" do
|
10
|
-
define_method_for('dd/mm/yyyy').call('2', '1', '2000').should == [2000,1,2,nil,nil,nil,nil]
|
10
|
+
define_method_for('dd/mm/yyyy').call('2', '1', '2000').should == [2000,1,2,nil,nil,nil,nil,nil]
|
11
11
|
end
|
12
12
|
|
13
13
|
it "should define method which outputs time array" do
|
14
|
-
define_method_for('hh:nn:ss').call('01', '02', '03').should == [nil,nil,nil,1,2,3,nil]
|
14
|
+
define_method_for('hh:nn:ss').call('01', '02', '03').should == [nil,nil,nil,1,2,3,nil,nil]
|
15
15
|
end
|
16
16
|
|
17
17
|
it "should define method which outputs time array with meridian 'pm' adjusted hour" do
|
18
|
-
define_method_for('hh:nn:ss ampm').call('01', '02', '03', 'pm').should == [nil,nil,nil,13,2,3,nil]
|
18
|
+
define_method_for('hh:nn:ss ampm').call('01', '02', '03', 'pm').should == [nil,nil,nil,13,2,3,nil,nil]
|
19
19
|
end
|
20
20
|
|
21
21
|
it "should define method which outputs time array with meridian 'am' unadjusted hour" do
|
22
|
-
define_method_for('hh:nn:ss ampm').call('01', '02', '03', 'am').should == [nil,nil,nil,1,2,3,nil]
|
22
|
+
define_method_for('hh:nn:ss ampm').call('01', '02', '03', 'am').should == [nil,nil,nil,1,2,3,nil,nil]
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should define method which outputs time array with microseconds" do
|
26
|
-
define_method_for('hh:nn:ss.u').call('01', '02', '03', '99').should == [nil,nil,nil,1,2,3,990000]
|
26
|
+
define_method_for('hh:nn:ss.u').call('01', '02', '03', '99').should == [nil,nil,nil,1,2,3,990000,nil]
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should define method which outputs datetime array with zone offset" do
|
30
30
|
define_method_for('yyyy-mm-dd hh:nn:ss.u zo').call('2001', '02', '03', '04', '05', '06', '99', '+10:00').should == [2001,2,3,4,5,6,990000,36000]
|
31
31
|
end
|
32
|
+
|
33
|
+
it "should define method which outputs datetime array with timezone string" do
|
34
|
+
define_method_for('yyyy-mm-dd hh:nn:ss.u tz').call('2001', '02', '03', '04', '05', '06', '99', 'EST').should == [2001,2,3,4,5,6,990000,'EST']
|
35
|
+
end
|
32
36
|
end
|
33
37
|
|
34
38
|
context "compiled regexp" do
|
@@ -26,7 +26,7 @@ describe Timeliness::Formats do
|
|
26
26
|
it "should add new format with higher precedence" do
|
27
27
|
formats.add_formats(:time, "ss:hh:nn", :before => 'hh:nn:ss')
|
28
28
|
time_array = parser._parse('59:23:58', :time)
|
29
|
-
time_array.should == [nil,nil,nil,23,58,59,nil]
|
29
|
+
time_array.should == [nil,nil,nil,23,58,59,nil,nil]
|
30
30
|
end
|
31
31
|
|
32
32
|
it "should raise error if :before format does not exist" do
|
@@ -45,17 +45,18 @@ describe Timeliness::Formats do
|
|
45
45
|
@default_formats = formats.time_formats.dup
|
46
46
|
end
|
47
47
|
|
48
|
-
it "should remove format from
|
48
|
+
it "should remove a single format from the formats array for type" do
|
49
49
|
formats.remove_formats(:time, 'h.nn_ampm')
|
50
|
-
formats.time_formats.should_not include(
|
50
|
+
formats.time_formats.should_not include('h.nn_ampm')
|
51
51
|
end
|
52
52
|
|
53
|
-
it "should remove multiple formats from
|
54
|
-
formats.remove_formats(:time, 'h.nn_ampm')
|
55
|
-
formats.time_formats.should_not include(
|
53
|
+
it "should remove multiple formats from formats array for type" do
|
54
|
+
formats.remove_formats(:time, 'h:nn', 'h.nn_ampm')
|
55
|
+
formats.time_formats.should_not include('h:nn')
|
56
|
+
formats.time_formats.should_not include('h.nn_ampm')
|
56
57
|
end
|
57
58
|
|
58
|
-
it "should
|
59
|
+
it "should prevent parsing of removed format" do
|
59
60
|
should_parse('2.12am', :time)
|
60
61
|
formats.remove_formats(:time, 'h.nn_ampm')
|
61
62
|
should_not_parse('2.12am', :time)
|
@@ -73,9 +74,9 @@ describe Timeliness::Formats do
|
|
73
74
|
|
74
75
|
context "use_euro_formats" do
|
75
76
|
it "should allow ambiguous date to be parsed as European format" do
|
76
|
-
parser._parse('01/02/2000', :date).should == [2000,1,2,nil,nil,nil,nil]
|
77
|
+
parser._parse('01/02/2000', :date).should == [2000,1,2,nil,nil,nil,nil,nil]
|
77
78
|
formats.use_euro_formats
|
78
|
-
parser._parse('01/02/2000', :date).should == [2000,2,1,nil,nil,nil,nil]
|
79
|
+
parser._parse('01/02/2000', :date).should == [2000,2,1,nil,nil,nil,nil,nil]
|
79
80
|
end
|
80
81
|
end
|
81
82
|
|
@@ -85,9 +86,9 @@ describe Timeliness::Formats do
|
|
85
86
|
end
|
86
87
|
|
87
88
|
it "should allow ambiguous date to be parsed as European format" do
|
88
|
-
parser._parse('01/02/2000', :date).should == [2000,2,1,nil,nil,nil,nil]
|
89
|
+
parser._parse('01/02/2000', :date).should == [2000,2,1,nil,nil,nil,nil,nil]
|
89
90
|
formats.use_us_formats
|
90
|
-
parser._parse('01/02/2000', :date).should == [2000,1,2,nil,nil,nil,nil]
|
91
|
+
parser._parse('01/02/2000', :date).should == [2000,1,2,nil,nil,nil,nil,nil]
|
91
92
|
end
|
92
93
|
end
|
93
94
|
end
|
@@ -71,11 +71,36 @@ describe Timeliness::Parser do
|
|
71
71
|
time.utc_offset.should == 1.hour
|
72
72
|
end
|
73
73
|
end
|
74
|
+
|
75
|
+
context "without ActiveSupport loaded" do
|
76
|
+
it 'should output message' do
|
77
|
+
lambda {
|
78
|
+
Time.should_receive(:use_zone).and_raise(NoMethodError.new("undefined method `zone' for Time:Class"))
|
79
|
+
time = parse("2000-06-01 12:13:14", :datetime, :zone => 'London')
|
80
|
+
}.should raise_error(Timeliness::Parser::MissingTimezoneSupport)
|
81
|
+
end
|
82
|
+
end
|
74
83
|
end
|
75
84
|
|
76
85
|
describe "for time type" do
|
77
|
-
|
78
|
-
|
86
|
+
context "with date from date_for_time_type" do
|
87
|
+
before do
|
88
|
+
@original = Timeliness.date_for_time_type
|
89
|
+
end
|
90
|
+
|
91
|
+
it 'should return date array' do
|
92
|
+
Timeliness.date_for_time_type = [2010,1,1]
|
93
|
+
parse('12:13:14', :time).should == Time.local(2010,1,1,12,13,14)
|
94
|
+
end
|
95
|
+
|
96
|
+
it 'should return date array evaluated lambda' do
|
97
|
+
Timeliness.date_for_time_type = lambda { Time.local(2010,2,1) }
|
98
|
+
parse('12:13:14', :time).should == Time.local(2010,2,1,12,13,14)
|
99
|
+
end
|
100
|
+
|
101
|
+
after do
|
102
|
+
Timeliness.date_for_time_type = @original
|
103
|
+
end
|
79
104
|
end
|
80
105
|
|
81
106
|
context "with :now option" do
|
@@ -107,54 +132,54 @@ describe Timeliness::Parser do
|
|
107
132
|
context "with type" do
|
108
133
|
it "should return date array from date string" do
|
109
134
|
time_array = parser._parse('2000-02-01', :date)
|
110
|
-
time_array.should == [2000,2,1,nil,nil,nil,nil]
|
135
|
+
time_array.should == [2000,2,1,nil,nil,nil,nil,nil]
|
111
136
|
end
|
112
137
|
|
113
138
|
it "should return time array from time string" do
|
114
139
|
time_array = parser._parse('12:13:14', :time)
|
115
|
-
time_array.should == [nil,nil,nil,12,13,14,nil]
|
140
|
+
time_array.should == [nil,nil,nil,12,13,14,nil,nil]
|
116
141
|
end
|
117
142
|
|
118
143
|
it "should return datetime array from datetime string" do
|
119
144
|
time_array = parser._parse('2000-02-01 12:13:14', :datetime)
|
120
|
-
time_array.should == [2000,2,1,12,13,14,nil]
|
145
|
+
time_array.should == [2000,2,1,12,13,14,nil,nil]
|
121
146
|
end
|
122
147
|
|
123
148
|
it "should return date array from date string when type is datetime" do
|
124
149
|
time_array = parser._parse('2000-02-01', :datetime)
|
125
|
-
time_array.should == [2000,2,1,nil,nil,nil,nil]
|
150
|
+
time_array.should == [2000,2,1,nil,nil,nil,nil,nil]
|
126
151
|
end
|
127
152
|
|
128
153
|
it "should return datetime array from datetime string when type is date" do
|
129
154
|
time_array = parser._parse('2000-02-01 12:13:14', :date)
|
130
|
-
time_array.should == [2000,2,1,12,13,14,nil]
|
155
|
+
time_array.should == [2000,2,1,12,13,14,nil,nil]
|
131
156
|
end
|
132
157
|
end
|
133
158
|
|
134
159
|
context "with no type" do
|
135
160
|
it "should return date array from date string" do
|
136
161
|
time_array = parser._parse('2000-02-01')
|
137
|
-
time_array.should == [2000,2,1,nil,nil,nil,nil]
|
162
|
+
time_array.should == [2000,2,1,nil,nil,nil,nil,nil]
|
138
163
|
end
|
139
164
|
|
140
165
|
it "should return time array from time string" do
|
141
166
|
time_array = parser._parse('12:13:14', :time)
|
142
|
-
time_array.should == [nil,nil,nil,12,13,14,nil]
|
167
|
+
time_array.should == [nil,nil,nil,12,13,14,nil,nil]
|
143
168
|
end
|
144
169
|
|
145
170
|
it "should return datetime array from datetime string" do
|
146
171
|
time_array = parser._parse('2000-02-01 12:13:14')
|
147
|
-
time_array.should == [2000,2,1,12,13,14,nil]
|
172
|
+
time_array.should == [2000,2,1,12,13,14,nil,nil]
|
148
173
|
end
|
149
174
|
|
150
175
|
it "should return date array from date string when type is datetime" do
|
151
176
|
time_array = parser._parse('2000-02-01')
|
152
|
-
time_array.should == [2000,2,1,nil,nil,nil,nil]
|
177
|
+
time_array.should == [2000,2,1,nil,nil,nil,nil,nil]
|
153
178
|
end
|
154
179
|
|
155
180
|
it "should return datetime array from datetime string when type is date" do
|
156
181
|
time_array = parser._parse('2000-02-01 12:13:14')
|
157
|
-
time_array.should == [2000,2,1,12,13,14,nil]
|
182
|
+
time_array.should == [2000,2,1,12,13,14,nil,nil]
|
158
183
|
end
|
159
184
|
end
|
160
185
|
|
@@ -205,7 +230,7 @@ describe Timeliness::Parser do
|
|
205
230
|
context "with :format option" do
|
206
231
|
it "should return values if string matches specified format" do
|
207
232
|
time_array = parser._parse('2000-02-01 12:13:14', :datetime, :format => 'yyyy-mm-dd hh:nn:ss')
|
208
|
-
time_array.should == [2000,2,1,12,13,14,nil]
|
233
|
+
time_array.should == [2000,2,1,12,13,14,nil,nil]
|
209
234
|
end
|
210
235
|
|
211
236
|
it "should return nil if string does not match specified format" do
|
@@ -217,21 +242,21 @@ describe Timeliness::Parser do
|
|
217
242
|
context "date with ambiguous year" do
|
218
243
|
it "should return year in current century if year below threshold" do
|
219
244
|
time_array = parser._parse('01-02-29', :date)
|
220
|
-
time_array.should == [2029,2,1,nil,nil,nil,nil]
|
245
|
+
time_array.should == [2029,2,1,nil,nil,nil,nil,nil]
|
221
246
|
end
|
222
247
|
|
223
248
|
it "should return year in last century if year at or above threshold" do
|
224
249
|
time_array = parser._parse('01-02-30', :date)
|
225
|
-
time_array.should == [1930,2,1,nil,nil,nil,nil]
|
250
|
+
time_array.should == [1930,2,1,nil,nil,nil,nil,nil]
|
226
251
|
end
|
227
252
|
|
228
253
|
it "should allow custom threshold" do
|
229
254
|
default = Timeliness.ambiguous_year_threshold
|
230
255
|
Timeliness.ambiguous_year_threshold = 40
|
231
256
|
time_array = parser._parse('01-02-39', :date)
|
232
|
-
time_array.should == [2039,2,1,nil,nil,nil,nil]
|
257
|
+
time_array.should == [2039,2,1,nil,nil,nil,nil,nil]
|
233
258
|
time_array = parser._parse('01-02-40', :date)
|
234
|
-
time_array.should == [1940,2,1,nil,nil,nil,nil]
|
259
|
+
time_array.should == [1940,2,1,nil,nil,nil,nil,nil]
|
235
260
|
Timeliness.ambiguous_year_threshold = default
|
236
261
|
end
|
237
262
|
end
|
data/timeliness.gemspec
CHANGED
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = %q{timeliness}
|
5
|
-
s.version = "0.
|
5
|
+
s.version = "0.2.0"
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ["Adam Meehan"]
|
9
|
-
s.date = %q{2010-10-
|
9
|
+
s.date = %q{2010-10-27}
|
10
10
|
s.description = %q{Fast date/time parser with customisable formats and I18n support.}
|
11
11
|
s.email = %q{adam.meehan@gmail.com}
|
12
12
|
s.extra_rdoc_files = ["README.rdoc", "CHANGELOG.rdoc"]
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: timeliness
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Adam Meehan
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-10-
|
18
|
+
date: 2010-10-27 00:00:00 +11:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|