iso8601 0.12.2 → 0.12.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.
- checksums.yaml +4 -4
- data/docs/date-time.md +86 -0
- data/docs/duration.md +76 -0
- data/docs/time-interval.md +120 -0
- data/lib/iso8601/version.rb +1 -1
- data/spec/iso8601/date_spec.rb +91 -0
- data/spec/iso8601/date_time_spec.rb +154 -0
- data/spec/iso8601/days_spec.rb +44 -0
- data/spec/iso8601/duration_spec.rb +299 -0
- data/spec/iso8601/hours_spec.rb +44 -0
- data/spec/iso8601/minutes_spec.rb +44 -0
- data/spec/iso8601/months_spec.rb +98 -0
- data/spec/iso8601/seconds_spec.rb +44 -0
- data/spec/iso8601/time_interval_spec.rb +520 -0
- data/spec/iso8601/time_spec.rb +110 -0
- data/spec/iso8601/weeks_spec.rb +46 -0
- data/spec/iso8601/years_spec.rb +70 -0
- data/spec/spec_helper.rb +12 -0
- metadata +48 -10
- data/CONTRIBUTING.md +0 -57
- data/Gemfile +0 -3
- data/iso8601.gemspec +0 -29
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b974875d177ceceff7f8d892867990e27f46718e57d7a8bb0119b8ccbddd77eb
|
4
|
+
data.tar.gz: 0b4e786f4abde832af5f5ceefb53c2478cffa0c3e8d9e997762ca54787fbf70a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e295765af84738b2bc1dc80ad2509a7e8bc065e61e32151ad979eb332cb5afe9b0042dd7072674be8259d985684616e8a0c9890c88cc29eefee9391ffd248924
|
7
|
+
data.tar.gz: 5ef627990b4f2c1ec2bcb98ec4caddc23928612a6b2895080cdcc84fd8a9295e7ce8564c04303d37b3c3ab934922cf9b1cdf8ced23571777f8c57ab2067a6ac5
|
data/docs/date-time.md
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
# Date Time, Date, Time
|
2
|
+
|
3
|
+
|
4
|
+
## Interface with core classes
|
5
|
+
|
6
|
+
ISO8601 classes provide a method `to_*` to convert to its core equivalent:
|
7
|
+
|
8
|
+
```ruby
|
9
|
+
ISO8601::DateTime#to_datetime # => #<DateTime: ...>
|
10
|
+
ISO8601::Date#to_date # => #<Date: ...>
|
11
|
+
ISO8601::Time#to_time # => #<Time: ...>
|
12
|
+
```
|
13
|
+
|
14
|
+
## Differences with core Date, Time and DateTime
|
15
|
+
|
16
|
+
### Reduced precision
|
17
|
+
|
18
|
+
Core `Date.parse` and `DateTime.parse` don't allow reduced precision. For
|
19
|
+
example:
|
20
|
+
|
21
|
+
```ruby
|
22
|
+
DateTime.parse('2014-05') # => ArgumentError: invalid date
|
23
|
+
```
|
24
|
+
|
25
|
+
But the standard covers this situation assuming any missing token as its lower
|
26
|
+
value:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
ISO8601::DateTime.new('2014-05').to_s # => "2014-05-01T00:00:00+00:00"
|
30
|
+
ISO8601::DateTime.new('2014').to_s # => "2014-01-01T00:00:00+00:00"
|
31
|
+
```
|
32
|
+
|
33
|
+
The same assumption happens in core classes with `.new`:
|
34
|
+
|
35
|
+
```ruby
|
36
|
+
DateTime.new(2014,5) # => #<DateTime: 2014-05-01T00:00:00+00:00 ((2456779j,0s,0n),+0s,2299161j)>
|
37
|
+
DateTime.new(2014) # => #<DateTime: 2014-01-01T00:00:00+00:00 ((2456659j,0s,0n),+0s,2299161j)>
|
38
|
+
```
|
39
|
+
|
40
|
+
### Unmatched precision
|
41
|
+
|
42
|
+
Unmatched precison is handled strongly. Notice the time fragment is lost in
|
43
|
+
`DateTime.parse` with no warning only if the loose precision is in the time
|
44
|
+
component.
|
45
|
+
|
46
|
+
```ruby
|
47
|
+
ISO8601::DateTime.new('2014-05-06T101112') # => ISO8601::Errors::UnknownPattern
|
48
|
+
DateTime.parse('2014-05-06T101112') # => #<DateTime: 2014-05-06T00:00:00+00:00 ((2456784j,0s,0n),+0s,2299161j)>
|
49
|
+
|
50
|
+
ISO8601::DateTime.new('20140506T10:11:12') # => ISO8601::Errors::UnknownPattern
|
51
|
+
DateTime.parse('20140506T10:11:12') # => #<DateTime: 2014-05-06T10:11:12+00:00 ((2456784j,0s,0n),+0s,2299161j)>
|
52
|
+
```
|
53
|
+
|
54
|
+
### Strong pattern matching
|
55
|
+
|
56
|
+
Week dates raise an error when two digit days provied instead of return monday:
|
57
|
+
|
58
|
+
```ruby
|
59
|
+
ISO8601::DateTime.new('2014-W15-02') # => ISO8601::Errors::UnknownPattern
|
60
|
+
DateTime.new('2014-W15-02') # => #<Date: 2014-04-07 ((2456755j,0s,0n),+0s,2299161j)>
|
61
|
+
```
|
62
|
+
|
63
|
+
|
64
|
+
## Atomization
|
65
|
+
|
66
|
+
`DateTime#to_a` allows decomposing to an array of atoms:
|
67
|
+
|
68
|
+
```ruby
|
69
|
+
atoms = ISO8601::DateTime.new('2014-05-31T10:11:12Z').to_a # => [2014, 5, 31, 10, 11, 12, '+00:00']
|
70
|
+
dt = DateTime.new(*atoms)
|
71
|
+
```
|
72
|
+
|
73
|
+
## Sign
|
74
|
+
|
75
|
+
Ordinal dates keep the sign. `2014-001` is not the same as `-2014-001`.
|
76
|
+
|
77
|
+
|
78
|
+
## Fractional seconds precision
|
79
|
+
|
80
|
+
Fractional seconds for `ISO8601::DateTime` and `ISO8601::Time` are rounded to
|
81
|
+
one decimal.
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
ISO8601::DateTime.new('2015-02-03T10:11:12.12').second #=> 12.1
|
85
|
+
ISO8601::Time.new('T10:11:12.16').second #=> 12.2
|
86
|
+
```
|
data/docs/duration.md
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
# Duration
|
2
|
+
|
3
|
+
> Durations are a component of time intervals and define the amount of
|
4
|
+
> intervening time in a time interval. Source: [Wikipedia ISO8601](https://en.wikipedia.org/wiki/ISO_8601#Durations)
|
5
|
+
|
6
|
+
See [Time Interval](time-interval.md) for working with specific intervals of
|
7
|
+
time.
|
8
|
+
|
9
|
+
## Supported patterns
|
10
|
+
|
11
|
+
```
|
12
|
+
PnYnMnDTnHnMnS
|
13
|
+
PnW
|
14
|
+
```
|
15
|
+
|
16
|
+
`P<date>T<time>` will not be implemented.
|
17
|
+
|
18
|
+
|
19
|
+
## Usage
|
20
|
+
|
21
|
+
Some times using durations might be more convenient than using time intervals:
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
duration = ISO8601::Duration.new('PT10H')
|
25
|
+
duration.to_seconds # => 36000.0
|
26
|
+
```
|
27
|
+
|
28
|
+
You can reuse the duration with a time interval:
|
29
|
+
|
30
|
+
```ruby
|
31
|
+
start_time = ISO8601::DateTime.new('2015-01-01T10:11:12Z')
|
32
|
+
time_interval = ISO8601::TimeInterval.from_duration(start_time, duration)
|
33
|
+
time_interval.size # => 36000.0
|
34
|
+
end_time = ISO8601::DateTime.new('2015-01-01T10:11:12Z')
|
35
|
+
time_interval = ISO8601::TimeInterval.from_duration(duration, end_time)
|
36
|
+
```
|
37
|
+
|
38
|
+
Or use an ad-hoc base:
|
39
|
+
|
40
|
+
```ruby
|
41
|
+
base = ISO8601::DateTime.new('2015-01-01T10:11:12Z')
|
42
|
+
duration = ISO8601::Duration.new('PT10H')
|
43
|
+
duration.to_seconds(base) # => 36000.0
|
44
|
+
```
|
45
|
+
|
46
|
+
**Warning**: When using durations without base, the result of `#to_seconds` is
|
47
|
+
an _average_. See the atoms' implementation for details.
|
48
|
+
|
49
|
+
|
50
|
+
# Operate with durations
|
51
|
+
|
52
|
+
The `ISO8601::Duration` has the concept of sign to be able to represent negative
|
53
|
+
values:
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
(ISO8601::Duration.new('PT10S') - ISO8601::Duration.new('PT12S')).to_s #=> '-PT2S'
|
57
|
+
(ISO8601::Duration.new('-PT10S') + ISO8601::Duration.new('PT12S')).to_s #=> 'PT2S'
|
58
|
+
```
|
59
|
+
|
60
|
+
You can also inspect a duration by atom:
|
61
|
+
|
62
|
+
```
|
63
|
+
duration = ISO8601::Duration.new('P2Y1MT2H')
|
64
|
+
duration.years # => #<ISO8601::Years ... @atom=2.0>
|
65
|
+
duration.months # => #<ISO8601::Months ... @atom=1.0>
|
66
|
+
duration.days # => #<ISO8601::Days ... @atom=0>
|
67
|
+
duration.hours # => #<ISO8601::Hours ... @atom=2.0>
|
68
|
+
duration.minutes # => #<ISO8601::Hours ... @atom=0.0>
|
69
|
+
duration.seconds # => #<ISO8601::Hours ... @atom=0.0>
|
70
|
+
```
|
71
|
+
|
72
|
+
Or get back the pattern:
|
73
|
+
|
74
|
+
```ruby
|
75
|
+
duration.to_s # => 'P2Y1MT2H'
|
76
|
+
```
|
@@ -0,0 +1,120 @@
|
|
1
|
+
# Time Interval
|
2
|
+
|
3
|
+
> A time interval is the intervening time between two time points.
|
4
|
+
Source: [Wikipedia ISO8601](https://en.wikipedia.org/wiki/ISO_8601#Time_intervals)
|
5
|
+
|
6
|
+
This library implements the Time Interval type via [`ISO8601::TimeInterval`](../lib/iso8601/time_interval.rb)
|
7
|
+
with the following constructors:
|
8
|
+
|
9
|
+
* `TimeInterval.new(String)` (or `TimeInterval.parse(String)`)
|
10
|
+
* `TimeInterval.from_duration(Duration, Hash<DateTime>)`
|
11
|
+
* `TimeInterval.from_datetime(DateTime, DateTime)`
|
12
|
+
|
13
|
+
|
14
|
+
## Supported patterns
|
15
|
+
|
16
|
+
```
|
17
|
+
<start>/<end>
|
18
|
+
<start>/<duration>
|
19
|
+
<duration>/<end>
|
20
|
+
```
|
21
|
+
|
22
|
+
Where `<start>` and `<end>` are points in time and `<duration>` is an amount of
|
23
|
+
time.
|
24
|
+
|
25
|
+
The pattern `<duration>` is not implemented; instead, you can use
|
26
|
+
[`TimeInterval.from_duration`](../lib/iso8601/time_interval.rb#L70).
|
27
|
+
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
### `<start>/<end>`
|
32
|
+
|
33
|
+
The resulting time interval will have a starting point based on the provided
|
34
|
+
`<start>` pattern and an ending point based on the provided `<end>` pattern.
|
35
|
+
|
36
|
+
```ruby
|
37
|
+
ti = ISO8601::TimeInterval.parse('2015-12-12T19:53:00Z/2015-12-13T19:53:00Z')
|
38
|
+
ti.start_time.to_s # => '2015-12-12T19:53:00Z'
|
39
|
+
ti.end_time.to_s # => '2015-12-13T19:53:00Z'
|
40
|
+
ti.size # => 86_400.0
|
41
|
+
```
|
42
|
+
|
43
|
+
### `<start>/<duration>`
|
44
|
+
|
45
|
+
The resulting time interval will have a starting point based on the provided
|
46
|
+
`<start>` pattern and an ending point result of `<start> + <duration>`.
|
47
|
+
|
48
|
+
```ruby
|
49
|
+
ti = ISO8601::TimeInterval.parse('2015-12-12T19:53:00Z/P1D')
|
50
|
+
ti.start_time.to_s # => '2015-12-12T19:53:00Z'
|
51
|
+
ti.end_time.to_s # => '2015-12-13T19:53:00Z'
|
52
|
+
ti.size # => 86_400.0
|
53
|
+
```
|
54
|
+
|
55
|
+
### `<duration>/<end>`
|
56
|
+
|
57
|
+
The resulting time interval will have a starting point result of
|
58
|
+
`<end> - <duration>` and an ending point based on the provided `<end>` pattern.
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
ti = ISO8601::TimeInterval.parse('P1D/2015-12-13T19:53:00Z')
|
62
|
+
ti.start_time.to_s # => '2015-12-12T19:53:00Z'
|
63
|
+
ti.end_time.to_s # => '2015-12-13T19:53:00Z'
|
64
|
+
ti.size # => 86_400.0
|
65
|
+
```
|
66
|
+
|
67
|
+
|
68
|
+
### `TimeInterval.from_duration`
|
69
|
+
|
70
|
+
```ruby
|
71
|
+
duration = ISO8601::Duration.new('P1D`)
|
72
|
+
start_time = ISO8601::DateTime.new('2015-12-12T19:53:00Z')
|
73
|
+
ti = ISO8601::TimeInterval.from_duration(start_time, duration)
|
74
|
+
ti.start_time.to_s # => '2015-12-12T19:53:00Z'
|
75
|
+
ti.end_time.to_s # => '2015-12-13T19:53:00Z'
|
76
|
+
ti.size # => 86_400.0
|
77
|
+
|
78
|
+
|
79
|
+
end_time = ISO8601::DateTime.new('2015-12-13T19:53:00Z')
|
80
|
+
ti2 = ISO8601::TimeInterval.from_duration(duration, end_time)
|
81
|
+
ti2.start_time.to_s # => '2015-12-12T19:53:00Z'
|
82
|
+
ti2.end_time.to_s # => '2015-12-13T19:53:00Z'
|
83
|
+
ti2.size # => 86_400.0
|
84
|
+
```
|
85
|
+
|
86
|
+
### `TimeInterval.from_datetime`
|
87
|
+
|
88
|
+
This constructor is an alternative way to `<start>/<end>` via Ruby objects.
|
89
|
+
|
90
|
+
```ruby
|
91
|
+
start_time = ISO8601::DateTime.new('2015-12-12T19:53:00Z')
|
92
|
+
end_time = ISO8601::DateTime.new('2015-12-13T19:53:00Z')
|
93
|
+
ti2 = ISO8601::TimeInterval.from_duration(start_time, end_time)
|
94
|
+
ti2.start_time.to_s # => '2015-12-12T19:53:00Z'
|
95
|
+
ti2.end_time.to_s # => '2015-12-13T19:53:00Z'
|
96
|
+
ti2.size # => 86_400.0
|
97
|
+
```
|
98
|
+
|
99
|
+
## Operate with time intervals
|
100
|
+
|
101
|
+
`TimeInterval` is `Comparable`, so you can use the usual `<`, `>`, `<=`, `>=`,
|
102
|
+
`==` to compare against another `TimeInterval`. Is equivalent to get the
|
103
|
+
amount of seconds via `#to_f` and compare the resulting numbers.
|
104
|
+
|
105
|
+
A time interval can be viewed as an ordered set of datetime elements:
|
106
|
+
|
107
|
+
* `#empty?` checks if an interval is empty.
|
108
|
+
* `#include?` checks if a `DateTime` is part of the time interval.
|
109
|
+
* `#intersect?` checks if two time intervals overlap.
|
110
|
+
* `#intersection` returns the intersected time interval if the two intervals intersect.
|
111
|
+
* `#disjoint?` checks if two time intervals don't intersect.
|
112
|
+
* `#subset?` checks if a time interval is included in another one.
|
113
|
+
* `#superset?` checks if a time interval is included in another one.
|
114
|
+
* `#first` is the lower bound.
|
115
|
+
* `#last` is the upper bound.
|
116
|
+
* `#size` is the total amount of seconds.
|
117
|
+
|
118
|
+
|
119
|
+
You can convert a time interval into a string with `#to_s` or into a float via
|
120
|
+
`#to_f`.
|
data/lib/iso8601/version.rb
CHANGED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ISO8601::Date do
|
4
|
+
it "should raise an error for any unknown pattern" do
|
5
|
+
expect { ISO8601::Date.new('') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
6
|
+
expect { ISO8601::Date.new('2') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
7
|
+
expect { ISO8601::Date.new('20') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
8
|
+
expect { ISO8601::Date.new('201') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
9
|
+
expect { ISO8601::Date.new('2010-') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
10
|
+
expect { ISO8601::Date.new('2010-') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
11
|
+
expect { ISO8601::Date.new('20-05') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
12
|
+
expect { ISO8601::Date.new('2010-0') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
13
|
+
expect { ISO8601::Date.new('2010-0-09') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
14
|
+
expect { ISO8601::Date.new('2010-1-09') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
15
|
+
expect { ISO8601::Date.new('201001-09') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
16
|
+
expect { ISO8601::Date.new('201-0109') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
17
|
+
expect { ISO8601::Date.new('2014-W15-02') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should raise an error for a correct pattern but an invalid date" do
|
21
|
+
expect { ISO8601::Date.new('2010-01-32') }.to raise_error(ISO8601::Errors::RangeError)
|
22
|
+
expect { ISO8601::Date.new('2010-02-30') }.to raise_error(ISO8601::Errors::RangeError)
|
23
|
+
expect { ISO8601::Date.new('2010-13-30') }.to raise_error(ISO8601::Errors::RangeError)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should parse any allowed pattern" do
|
27
|
+
expect { ISO8601::Date.new('2010') }.to_not raise_error
|
28
|
+
expect { ISO8601::Date.new('2010-05') }.to_not raise_error
|
29
|
+
expect { ISO8601::Date.new('2010-05-09') }.to_not raise_error
|
30
|
+
expect { ISO8601::Date.new('2014-001') }.to_not raise_error
|
31
|
+
expect { ISO8601::Date.new('2014121') }.to_not raise_error
|
32
|
+
expect { ISO8601::Date.new('2014-W15') }.to_not raise_error
|
33
|
+
expect { ISO8601::Date.new('2014-W15-2') }.to_not raise_error
|
34
|
+
expect { ISO8601::Date.new('2014W15') }.to_not raise_error
|
35
|
+
expect { ISO8601::Date.new('2014W152') }.to_not raise_error
|
36
|
+
end
|
37
|
+
|
38
|
+
context 'reduced patterns' do
|
39
|
+
it "should parse correctly reduced dates" do
|
40
|
+
reduced_date = ISO8601::Date.new('20100509')
|
41
|
+
expect(reduced_date.year).to eq(2010)
|
42
|
+
expect(reduced_date.month).to eq(5)
|
43
|
+
expect(reduced_date.day).to eq(9)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "should return the right sign for the given year" do
|
48
|
+
expect(ISO8601::Date.new('-2014-05-31').year).to eq(-2014)
|
49
|
+
expect(ISO8601::Date.new('+2014-05-31').year).to eq(2014)
|
50
|
+
end
|
51
|
+
|
52
|
+
it "should respond to delegated casting methods" do
|
53
|
+
expect(ISO8601::Date.new('2014-12-11')).to respond_to(:to_s, :to_time, :to_date, :to_datetime)
|
54
|
+
end
|
55
|
+
|
56
|
+
describe '#+' do
|
57
|
+
it "should return the result of the addition of a number" do
|
58
|
+
expect((ISO8601::Date.new('2012-07-07') + 7).to_s).to eq('2012-07-14')
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
describe '#-' do
|
63
|
+
it "should return the result of the subtraction" do
|
64
|
+
expect((ISO8601::Date.new('2012-07-07') - 7).to_s).to eq('2012-06-30')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#to_a' do
|
69
|
+
it "should return an array of atoms" do
|
70
|
+
expect(ISO8601::Date.new('2014-05-31').to_a).to eq([2014, 5, 31])
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe '#atoms' do
|
75
|
+
it "should return an array of original atoms" do
|
76
|
+
expect(ISO8601::Date.new('2014-05-02').atoms).to eq([2014, 5, 2])
|
77
|
+
expect(ISO8601::Date.new('2014-05').atoms).to eq([2014, 5])
|
78
|
+
expect(ISO8601::Date.new('2014').atoms).to eq([2014])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
describe '#hash' do
|
83
|
+
it "should return the date hash" do
|
84
|
+
subject = ISO8601::Date.new('2014-08-16')
|
85
|
+
contrast = ISO8601::Date.new('2014-08-16')
|
86
|
+
|
87
|
+
expect(subject).to respond_to(:hash)
|
88
|
+
expect(subject.hash).to eq(contrast.hash)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -0,0 +1,154 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ISO8601::DateTime do
|
4
|
+
it "should raise a ISO8601::Errors::UnknownPattern for any unknown pattern" do
|
5
|
+
expect { ISO8601::DateTime.new('') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
6
|
+
expect { ISO8601::DateTime.new('2') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
7
|
+
expect { ISO8601::DateTime.new('20') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
8
|
+
expect { ISO8601::DateTime.new('201') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
9
|
+
expect { ISO8601::DateTime.new('2010-') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
10
|
+
expect { ISO8601::DateTime.new('2010-') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
11
|
+
expect { ISO8601::DateTime.new('20-05') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
12
|
+
expect { ISO8601::DateTime.new('2010-0') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
13
|
+
expect { ISO8601::DateTime.new('2010-0-09') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
14
|
+
expect { ISO8601::DateTime.new('2010-1-09') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
15
|
+
expect { ISO8601::DateTime.new('201001-09') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
16
|
+
expect { ISO8601::DateTime.new('201-0109') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
17
|
+
expect { ISO8601::DateTime.new('2010-05-09T103012+0400') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
18
|
+
expect { ISO8601::DateTime.new('20100509T10:30:12+04:00') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
19
|
+
expect { ISO8601::DateTime.new('2010-05T10:30:12Z') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
20
|
+
expect { ISO8601::DateTime.new('2010T10:30:12Z') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
21
|
+
expect { ISO8601::DateTime.new('2014-W15-02T10:11:12Z') }.to raise_error(ISO8601::Errors::UnknownPattern)
|
22
|
+
end
|
23
|
+
|
24
|
+
it "should raise a RangeError for a correct pattern but an invalid date" do
|
25
|
+
expect { ISO8601::DateTime.new('2010-01-32') }.to raise_error(ISO8601::Errors::RangeError)
|
26
|
+
expect { ISO8601::DateTime.new('2010-02-30') }.to raise_error(ISO8601::Errors::RangeError)
|
27
|
+
expect { ISO8601::DateTime.new('2010-13-30') }.to raise_error(ISO8601::Errors::RangeError)
|
28
|
+
expect { ISO8601::DateTime.new('2010-12-30T25:00:00') }.to raise_error(ISO8601::Errors::RangeError)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "should parse any allowed pattern" do
|
32
|
+
expect { ISO8601::DateTime.new('2010') }.to_not raise_error
|
33
|
+
expect { ISO8601::DateTime.new('2010-05') }.to_not raise_error
|
34
|
+
expect { ISO8601::DateTime.new('2010-05-09') }.to_not raise_error
|
35
|
+
expect { ISO8601::DateTime.new('2010-05-09T10') }.to_not raise_error
|
36
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30') }.to_not raise_error
|
37
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30:12') }.to_not raise_error
|
38
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30:12Z') }.to_not raise_error
|
39
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30:12+04') }.to_not raise_error
|
40
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30:12+04:00') }.to_not raise_error
|
41
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30:12-04:00') }.to_not raise_error
|
42
|
+
expect { ISO8601::DateTime.new('2010-05-09T10:30:12-00:00') }.to_not raise_error
|
43
|
+
expect { ISO8601::DateTime.new('-2014-05-31T16:26:00Z') }.to_not raise_error
|
44
|
+
expect { ISO8601::DateTime.new('2014-05-31T16:26:10.5Z') }.to_not raise_error
|
45
|
+
expect { ISO8601::DateTime.new('2014-05-31T16:26:10,5Z') }.to_not raise_error
|
46
|
+
expect { ISO8601::DateTime.new('T10:30:12Z') }.to_not raise_error
|
47
|
+
expect { ISO8601::DateTime.new('2014-001') }.to_not raise_error
|
48
|
+
expect { ISO8601::DateTime.new('2014121') }.to_not raise_error
|
49
|
+
expect { ISO8601::DateTime.new('2014-121T10:11:12Z') }.to_not raise_error
|
50
|
+
expect { ISO8601::DateTime.new('20100509T103012+0400') }.to_not raise_error
|
51
|
+
expect { ISO8601::DateTime.new('20100509') }.to_not raise_error
|
52
|
+
expect { ISO8601::DateTime.new('T103012+0400') }.to_not raise_error
|
53
|
+
expect { ISO8601::DateTime.new('T103012+04') }.to_not raise_error
|
54
|
+
expect { ISO8601::DateTime.new('T103012+04') }.to_not raise_error
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'reduced patterns' do
|
58
|
+
it "should parse correctly reduced dates" do
|
59
|
+
reduced_date = ISO8601::DateTime.new('20100509')
|
60
|
+
expect(reduced_date.year).to eq(2010)
|
61
|
+
expect(reduced_date.month).to eq(5)
|
62
|
+
expect(reduced_date.day).to eq(9)
|
63
|
+
end
|
64
|
+
it "should parse correctly reduced times" do
|
65
|
+
reduced_time = ISO8601::DateTime.new('T101112Z')
|
66
|
+
expect(reduced_time.hour).to eq(10)
|
67
|
+
expect(reduced_time.minute).to eq(11)
|
68
|
+
expect(reduced_time.second).to eq(12)
|
69
|
+
end
|
70
|
+
it "should parse correctly reduced date times" do
|
71
|
+
reduced_datetime = ISO8601::DateTime.new('20140531T101112Z')
|
72
|
+
expect(reduced_datetime.year).to eq(2014)
|
73
|
+
expect(reduced_datetime.month).to eq(5)
|
74
|
+
expect(reduced_datetime.day).to eq(31)
|
75
|
+
expect(reduced_datetime.hour).to eq(10)
|
76
|
+
expect(reduced_datetime.minute).to eq(11)
|
77
|
+
expect(reduced_datetime.second).to eq(12)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
it "should return each atomic value" do
|
82
|
+
dt = ISO8601::DateTime.new('2010-05-09T12:02:01+04:00')
|
83
|
+
expect(dt.year).to eq(2010)
|
84
|
+
expect(dt.month).to eq(5)
|
85
|
+
expect(dt.day).to eq(9)
|
86
|
+
expect(dt.hour).to eq(12)
|
87
|
+
expect(dt.minute).to eq(2)
|
88
|
+
expect(dt.second).to eq(1)
|
89
|
+
expect(dt.zone).to eq('+04:00')
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should return the right sign for the given year" do
|
93
|
+
expect(ISO8601::DateTime.new('-2014-05-31T16:26:00Z').year).to eq(-2014)
|
94
|
+
expect(ISO8601::DateTime.new('+2014-05-31T16:26:00Z').year).to eq(2014)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should respond to delegated casting methods" do
|
98
|
+
dt = ISO8601::DateTime.new('2014-12-11T10:09:08Z')
|
99
|
+
expect(dt).to respond_to(:to_s, :to_time, :to_date, :to_datetime)
|
100
|
+
end
|
101
|
+
|
102
|
+
describe '#+' do
|
103
|
+
it "should return the result of the addition of a number" do
|
104
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20Z') + 10).to_s).to eq('2012-07-07T20:20:30+00:00')
|
105
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20.5Z') + 10).to_s).to eq('2012-07-07T20:20:30.5+00:00')
|
106
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20+02:00') + 10.09).to_s).to eq('2012-07-07T20:20:30.1+02:00')
|
107
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20+02:00') + 10.1).to_s).to eq('2012-07-07T20:20:30.1+02:00')
|
108
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20+02:00') + 10).second).to eq(30)
|
109
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20.5Z') + 10).second).to eq(30.5)
|
110
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20+02:00') + 10.09).second).to eq(30.1)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
describe '#-' do
|
115
|
+
it "should return the result of the subtraction of a number" do
|
116
|
+
expect((ISO8601::DateTime.new('2012-07-07T20:20:20Z') - 10).to_s).to eq('2012-07-07T20:20:10+00:00')
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
describe '#to_a' do
|
121
|
+
it "should return an array of atoms" do
|
122
|
+
dt = ISO8601::DateTime.new('2014-05-31T19:29:39Z').to_a
|
123
|
+
expect(dt).to be_kind_of(Array)
|
124
|
+
expect(dt).to eq([2014, 5, 31, 19, 29, 39, '+00:00'])
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
describe '#hash' do
|
129
|
+
it "should return the datetime hash" do
|
130
|
+
subject = ISO8601::DateTime.new('2014-08-16T20:11:10Z')
|
131
|
+
contrast = ISO8601::DateTime.new('2014-08-16T20:11:10Z')
|
132
|
+
|
133
|
+
expect(subject.hash == contrast.hash).to be_truthy
|
134
|
+
expect(subject.hash).to eq(contrast.hash)
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
describe '#==' do
|
139
|
+
it "should identify loose precision datetimes" do
|
140
|
+
expect(ISO8601::DateTime.new('2014') == ISO8601::DateTime.new('2014')).to be_truthy
|
141
|
+
expect(ISO8601::DateTime.new('2014') == ISO8601::DateTime.new('2015')).to be_falsy
|
142
|
+
expect(ISO8601::DateTime.new('2014-10') == ISO8601::DateTime.new('2014-11')).to be_falsy
|
143
|
+
expect(ISO8601::DateTime.new('2014-10') == ISO8601::DateTime.new('2014-11')).to be_falsy
|
144
|
+
expect(ISO8601::DateTime.new('2014-10-11T12') == ISO8601::DateTime.new('2014-10-11T13')).to be_falsy
|
145
|
+
expect(ISO8601::DateTime.new('2014-10-11T12:13') == ISO8601::DateTime.new('2014-10-11T12:14')).to be_falsy
|
146
|
+
expect(ISO8601::DateTime.new('2014-10-11T12:13:10') == ISO8601::DateTime.new('2014-10-11T12:13:10.0')).to be_truthy
|
147
|
+
expect(ISO8601::DateTime.new('2014-10-11T12:13:10.1') == ISO8601::DateTime.new('2014-10-11T12:13:10.2')).to be_falsy
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should identify as the same when two dates with different timezones are the same timestamp" do
|
151
|
+
expect(ISO8601::DateTime.new('2014-10-11T12:13:14Z') == ISO8601::DateTime.new('2014-10-11T13:13:14+01:00')).to be_truthy
|
152
|
+
end
|
153
|
+
end
|
154
|
+
end
|