iso8601 0.8.7 → 0.9.0

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.
Files changed (48) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +17 -0
  3. data/CONTRIBUTING.md +58 -0
  4. data/Gemfile +2 -2
  5. data/README.md +28 -102
  6. data/docs/date-time.md +86 -0
  7. data/docs/duration.md +77 -0
  8. data/docs/time-interval.md +120 -0
  9. data/iso8601.gemspec +43 -6
  10. data/lib/iso8601.rb +15 -7
  11. data/lib/iso8601/atomic.rb +78 -0
  12. data/lib/iso8601/date.rb +35 -10
  13. data/lib/iso8601/date_time.rb +14 -3
  14. data/lib/iso8601/days.rb +47 -0
  15. data/lib/iso8601/duration.rb +115 -99
  16. data/lib/iso8601/errors.rb +13 -1
  17. data/lib/iso8601/hours.rb +43 -0
  18. data/lib/iso8601/minutes.rb +43 -0
  19. data/lib/iso8601/months.rb +98 -0
  20. data/lib/iso8601/seconds.rb +47 -0
  21. data/lib/iso8601/time.rb +43 -15
  22. data/lib/iso8601/time_interval.rb +392 -0
  23. data/lib/iso8601/version.rb +1 -1
  24. data/lib/iso8601/weeks.rb +43 -0
  25. data/lib/iso8601/years.rb +80 -0
  26. data/spec/iso8601/date_spec.rb +0 -6
  27. data/spec/iso8601/date_time_spec.rb +0 -8
  28. data/spec/iso8601/days_spec.rb +44 -0
  29. data/spec/iso8601/duration_spec.rb +103 -99
  30. data/spec/iso8601/hours_spec.rb +44 -0
  31. data/spec/iso8601/minutes_spec.rb +44 -0
  32. data/spec/iso8601/months_spec.rb +86 -0
  33. data/spec/iso8601/seconds_spec.rb +44 -0
  34. data/spec/iso8601/time_interval_spec.rb +416 -0
  35. data/spec/iso8601/time_spec.rb +0 -6
  36. data/spec/iso8601/weeks_spec.rb +46 -0
  37. data/spec/iso8601/years_spec.rb +69 -0
  38. metadata +37 -19
  39. data/.dockerignore +0 -7
  40. data/.editorconfig +0 -9
  41. data/.gitignore +0 -19
  42. data/.rubocop.yml +0 -38
  43. data/.travis.yml +0 -19
  44. data/Dockerfile +0 -10
  45. data/Makefile +0 -19
  46. data/circle.yml +0 -13
  47. data/lib/iso8601/atoms.rb +0 -279
  48. data/spec/iso8601/atoms_spec.rb +0 -329
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: da8595f5fe628655a291148485dbd7d24f65688c
4
- data.tar.gz: 02f8ad412ea8b17eacbf4b0e9a3758c8f4bdc2c2
3
+ metadata.gz: 7ddae589523a353d89540217174b6d9ee8806be0
4
+ data.tar.gz: e0194acdcdc97a76bfa05ef1cf0389e01ab39d10
5
5
  SHA512:
6
- metadata.gz: e33d0e1b9016a1d5c41bf2b4c582ccbff2fb030e8d373151ac9f2e6fa09aaabb2126c160253c1e126a1ce4a4ffdfa4e607c61b74d09dc926cbabb880c9ddf47b
7
- data.tar.gz: 96d0336d8add6e8a91e82ef6d27fa1cfaf9cc1d0b54a010123d9b01d2b161135135a7b03c5d8e74422edb785a0948401a702e82c8c303a93713653dbce87506a
6
+ metadata.gz: d013dd70e31518034388484c891a4b407d475bafb178b762fc997a9927ac43a90cde015ac0cf308a1d713d3dc4a1cb1ee0d333e8f0e31cf93e2c0c75a859ec81
7
+ data.tar.gz: 6144023256e448874c926377449230a059145996d48ab355d04acba4f22d2bd497a8a11892a43bf46c76d10cd3775d9661ce41f6aa101d19938216d307ce54bb
@@ -1,3 +1,20 @@
1
+ ## 0.9.0
2
+
3
+ This version is **not compatible** with previous versions. Atoms and Durations
4
+ changed their interface when treating base dates so it is only applied when
5
+ computing the Atom length (e.g. `#to_seconds`). As a consequence, it is no
6
+ longer possible to do operations like `DateTime + Duration`.
7
+
8
+ * Add time intervals (thanks @Angelmmiguel).
9
+ * Remove `Duration#to_i`.
10
+ * Change `Duration#to_seconds` to accept a base `DateTime`.
11
+ * Remove duration dependency on a base date on the instance level.
12
+ * Change `Years#to_seconds` and `Months#to_seconds` to accept a base `DateTime`.
13
+ * Remove atom dependency on a base date on the instance level.
14
+ * Add `Atomic` mixin.
15
+ * Remove `Atom` abstract class.
16
+ * Allow `ISO8601::Duration` to perform operations with `Numeric` (thanks @Angelmmiguel).
17
+
1
18
  ## 0.8.7
2
19
 
3
20
  * Make `Atom` comparable with the same kind (thanks @glassbead0).
@@ -0,0 +1,58 @@
1
+ # Contributing
2
+
3
+ Thanks for taking the time to submit a pull request! These are the few
4
+ guidelines to keep things coherent.
5
+
6
+ [Fork the project](http://github.com/arnau/ISO8601/fork) and clone.
7
+
8
+ Create your _feature_ branch:
9
+
10
+ ```sh
11
+ git checkout -b features/xyz
12
+ ```
13
+
14
+ Set up your machine. I recommend using [Docker](https://docker.com):
15
+
16
+ ```sh
17
+ make install
18
+ ```
19
+
20
+ But of course you can go raw style
21
+
22
+ ```sh
23
+ bundle install
24
+ ```
25
+
26
+ Add your code and tests and check it passes:
27
+
28
+ ```sh
29
+ make test # mri, rbx, jruby
30
+ # or
31
+ make mri-test
32
+ make rbx-test
33
+ make jruby-test
34
+ ```
35
+
36
+ Or raw style
37
+
38
+ ```sh
39
+ bundle exec rspec
40
+ ```
41
+
42
+ Although not required, try to adhere to Rubocop's checks:
43
+
44
+ ```sh
45
+ make check
46
+ ```
47
+
48
+ Or raw style
49
+
50
+ ```sh
51
+ bundle exec rubocop
52
+ ```
53
+
54
+ Push your branch and submit a [Pull Request](https://github.com/arnau/iso8601/compare/).
55
+
56
+ Add a description of your proposed changes and why they are needed.
57
+
58
+ I'll review it as soon as I can.
data/Gemfile CHANGED
@@ -3,6 +3,6 @@ source 'http://rubygems.org'
3
3
  gemspec
4
4
 
5
5
  group :development do
6
- gem 'pry'
7
- gem 'pry-doc'
6
+ gem 'pry', '~> 0.10.3'
7
+ gem 'pry-doc', '~> 0.8.0'
8
8
  end
data/README.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # ISO8601
2
2
 
3
+ Version 0.9.0 is **not compatible** with previous versions. Atoms and Durations
4
+ changed their interface when treating base dates so it is only applied when
5
+ computing the Atom length (e.g. `#to_seconds`). As a consequence, it is no
6
+ longer possible to do operations like `DateTime + Duration`.
7
+
8
+ Version 1.0.0 will lock public interfaces.
9
+
10
+ Check the [changelog](https://github.com/arnau/ISO8601/blob/master/CHANGELOG.md) if you are upgrading from an older version.
11
+
3
12
  [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/arnau/ISO8601?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
4
13
 
5
14
  ISO8601 is a simple implementation of the ISO 8601 (Data elements and
@@ -14,132 +23,49 @@ times) standard.
14
23
 
15
24
  ## Supported versions
16
25
 
17
- * MRI 1.9.3, 2.0, 2.1, 2.2
26
+ * MRI 2.x
18
27
  * RBX 2
19
-
20
- Check the [changelog](https://github.com/arnau/ISO8601/blob/master/CHANGELOG.md) if you are upgrading from an older version.
28
+ * JRuby 9
21
29
 
22
30
  ## Documentation
23
31
 
24
- Check the [rubydoc documentation](http://www.rubydoc.info/gems/iso8601).
25
-
26
- ## Comments about this implementation
27
-
28
- ### Duration sign
29
-
30
- Because `Durations` and `DateTime` have a substraction method, `Durations` has
31
- sign to be able to represent negative values:
32
-
33
- (ISO8601::Duration.new('PT10S') - ISO8601::Duration.new('PT12S')).to_s #=> '-PT2S'
34
- (ISO8601::Duration.new('-PT10S') + ISO8601::Duration.new('PT12S')).to_s #=> 'PT2S'
35
-
36
- ### Fractional seconds precision
37
-
38
- Fractional seconds for `ISO8601::DateTime` and `ISO8601::Time` are rounded to
39
- one decimal.
40
-
41
- ISO8601::DateTime.new('2015-02-03T10:11:12.12').second #=> 12.1
42
- ISO8601::Time.new('T10:11:12.16').second #=> 12.2
43
-
44
-
45
- ## Differences with core Date, Time and DateTime
46
-
47
- Core `Date.parse` and `DateTime.parse` doesn't allow reduced precision. For
48
- example:
49
-
50
- DateTime.parse('2014-05') # => ArgumentError: invalid date
51
-
52
- But the standard covers this situation assuming any missing piece as its lower
53
- value:
54
-
55
- ISO8601::DateTime.new('2014-05').to_s # => "2014-05-01T00:00:00+00:00"
56
- ISO8601::DateTime.new('2014').to_s # => "2014-01-01T00:00:00+00:00"
57
-
58
- The same assumption happens in core classes with `.new`:
59
-
60
- DateTime.new(2014,5) # => #<DateTime: 2014-05-01T00:00:00+00:00 ((2456779j,0s,0n),+0s,2299161j)>
61
- DateTime.new(2014) # => #<DateTime: 2014-01-01T00:00:00+00:00 ((2456659j,0s,0n),+0s,2299161j)>
62
-
63
-
64
- The value of second in core classes are handled by two methods: `#second` and
65
- `#second_fraction`:
66
-
67
- dt = DateTime.parse('2014-05-06T10:11:12.5')
68
- dt.second # => 12
69
- dt.second_fraction # => (1/2)
70
-
71
- This gem approaches second fraction using floats:
32
+ Check the [rubydoc documentation](http://www.rubydoc.info/gems/iso8601). Or
33
+ take a look to the implementation notes:
72
34
 
73
- dt = ISO8601::DateTime.new('2014-05-06T10:11:12.5')
74
- dt.second # => 12.5
35
+ * [Date, Time, DateTime](docs/date-time.md)
36
+ * [Duration](docs/duration.md)
37
+ * [Time interval](docs/time-interval.md)
75
38
 
76
- Unmatching precison is handled strongly. Notice the time fragment is lost in
77
- `DateTime.parse` without warning only if the loose precision is in the time
78
- component.
79
39
 
80
- ISO8601::DateTime.new('2014-05-06T101112') # => ISO8601::Errors::UnknownPattern
81
- DateTime.parse('2014-05-06T101112') # => #<DateTime: 2014-05-06T00:00:00+00:00 ((2456784j,0s,0n),+0s,2299161j)>
82
-
83
- ISO8601::DateTime.new('20140506T10:11:12') # => ISO8601::Errors::UnknownPattern
84
- DateTime.parse('20140506T10:11:12') # => #<DateTime: 2014-05-06T10:11:12+00:00 ((2456784j,0s,0n),+0s,2299161j)>
85
-
86
-
87
- `DateTime#to_a` allow decomposing to an array of atoms:
88
-
89
- atoms = ISO8601::DateTime.new('2014-05-31T10:11:12Z').to_a # => [2014, 5, 31, 10, 11, 12, '+00:00']
90
- dt = DateTime.new(*atoms)
91
-
92
- Ordinal dates keep the sign. `2014-001` is not the same as `-2014-001`.
93
-
94
- Week dates raise an error when two digit days provied instead of return monday:
95
-
96
- ISO8601::DateTime.new('2014-W15-02') # => ISO8601::Errors::UnknownPattern
97
- DateTime.new('2014-W15-02') # => #<Date: 2014-04-07 ((2456755j,0s,0n),+0s,2299161j)>
98
-
99
-
100
- ## Compatibility with core classes
101
-
102
- Each ISO8601 class has a method `to_*` to convert to its core equivalent:
103
-
104
- `ISO8601::DateTime#to_datetime` -> `DateTime` (it actually delegates a couple of
105
- methods from `DateTime`). Check `lib/iso8601/date_time.rb:13`.
40
+ ## Testing
106
41
 
107
- `ISO8601::Date#to_date` -> `Date` (it actually delegates to a couple of methods
108
- from `Date`). Check `lib/iso8601/date.rb:18`
109
42
 
110
- `ISO8601::Time#to_time` -> `Time` (it actually delegates to a couple of methods
111
- from `Time`). Check `lib/iso8601/time.rb:15`
43
+ ### Docker
112
44
 
113
- `ISO8601::Atom#to_f` -> `Float`, `ISO8601::Atom#to_i` -> `Integer`
45
+ # Install Docker
46
+ $ make install
47
+ $ make test
114
48
 
49
+ You can alse target specific runtimes:
115
50
 
116
- ## Testing
51
+ $ make mri-test
52
+ $ make rbx-test
53
+ $ make jruby-test
117
54
 
118
55
  ### Raw
119
56
 
57
+ The old fashion way:
58
+
120
59
  # Install a Ruby flavour
121
60
  $ bundle install
122
61
  $ bundle exec rspec
123
62
 
124
- ### Docker
125
-
126
- This way is in an early stage so for now it's only possible to test one Ruby
127
- version (currently Ruby 2.2.)
128
-
129
- # Install Docker
130
- $ make install
131
- $ make test
132
63
 
133
64
  ## Contributing
134
65
 
135
66
  [Contributors](https://github.com/arnau/ISO8601/graphs/contributors)
136
67
 
137
- 1. Fork it (http://github.com/arnau/ISO8601/fork)
138
- 2. Create your feature branch (git checkout -b features/xyz)
139
- 3. Commit your changes (git commit -am 'Add XYZ')
140
- 4. Push to the branch (git push origin features/xyz)
141
- 5. Create new Pull Request
142
-
68
+ Please see [CONTRIBUTING.md](./CONTRIBUTING.md)
143
69
 
144
70
  ## License
145
71
 
@@ -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
+ ```
@@ -0,0 +1,77 @@
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
+ (e.g. you don't need or want a specific point in time).
23
+
24
+ ```ruby
25
+ duration = ISO8601::Duration.new('PT10H')
26
+ duration.to_seconds # => 36000.0
27
+ ```
28
+
29
+ Although you reuse the duration with a time interval:
30
+
31
+ ```ruby
32
+ start_time = ISO8601::DateTime.new('2015-01-01T10:11:12Z')
33
+ time_interval = ISO8601::TimeInterval.from_duration(start_time, duration)
34
+ time_interval.size # => 36000.0
35
+ end_time = ISO8601::DateTime.new('2015-01-01T10:11:12Z')
36
+ time_interval = ISO8601::TimeInterval.from_duration(duration, end_time)
37
+ ```
38
+
39
+ Or use an ad-hoc base:
40
+
41
+ ```ruby
42
+ base = ISO8601::DateTime.new('2015-01-01T10:11:12Z')
43
+ duration = ISO8601::Duration.new('PT10H')
44
+ duration.to_seconds(base) # => 36000.0
45
+ ```
46
+
47
+ **Warning**: When using durations without base, the result of `#to_seconds` is
48
+ an _average_. See the implementation of the atoms for details.
49
+
50
+
51
+ # Operate with durations
52
+
53
+ The `ISO8601::Duration` has the concept of sign to be able to represent negative
54
+ values:
55
+
56
+ ```ruby
57
+ (ISO8601::Duration.new('PT10S') - ISO8601::Duration.new('PT12S')).to_s #=> '-PT2S'
58
+ (ISO8601::Duration.new('-PT10S') + ISO8601::Duration.new('PT12S')).to_s #=> 'PT2S'
59
+ ```
60
+
61
+ You can also inspect a duration by atom:
62
+
63
+ ```
64
+ duration = ISO8601::Duration.new('P2Y1MT2H')
65
+ duration.years # => #<ISO8601::Years ... @atom=2.0>
66
+ duration.months # => #<ISO8601::Months ... @atom=1.0>
67
+ duration.days # => #<ISO8601::Days ... @atom=0>
68
+ duration.hours # => #<ISO8601::Hours ... @atom=2.0>
69
+ duration.minutes # => #<ISO8601::Hours ... @atom=0.0>
70
+ duration.seconds # => #<ISO8601::Hours ... @atom=0.0>
71
+ ```
72
+
73
+ Or get back the pattern:
74
+
75
+ ```ruby
76
+ duration.to_s # => 'P2Y1MT2H'
77
+ ```
@@ -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`.