Skip to content


Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Ruby parser to work with ISO8601 dateTimes and durations —



ISO8601 is a simple implementation of the ISO 8601 (Data elements and interchange formats — Information interchange — Representation of dates and times) standard.

Build status

Build Status Dependency Status Gem Version

Supported versions

  • MRI 1.9.3, 2.0, 2.1, 2.2
  • RBX 2

Check the changelog if you are upgrading from an older version.

Comments about this implementation

Duration sign

Because Durations and DateTime have a substraction method, Durations has sign to be able to represent negative values:

('PT10S') -'PT12S')).to_s  #=> '-PT2S'
('-PT10S') +'PT12S')).to_s #=> 'PT2S'

Fractional seconds precision

Fractional seconds for ISO8601::DateTime and ISO8601::Time are rounded to one decimal.'2015-02-03T10:11:12.12').second #=> 12.1'T10:11:12.16').second #=> 12.2

Differences with core Date, Time and DateTime

Core Date.parse and DateTime.parse doesn't allow reduced precision. For example:

DateTime.parse('2014-05') # => ArgumentError: invalid date

But the standard covers this situation assuming any missing piece as its lower value:'2014-05').to_s # => "2014-05-01T00:00:00+00:00"'2014').to_s # => "2014-01-01T00:00:00+00:00"

The same assumption happens in core classes with .new:,5) # => #<DateTime: 2014-05-01T00:00:00+00:00 ((2456779j,0s,0n),+0s,2299161j)> # => #<DateTime: 2014-01-01T00:00:00+00:00 ((2456659j,0s,0n),+0s,2299161j)>

The value of second in core classes are handled by two methods: #second and #second_fraction:

dt = DateTime.parse('2014-05-06T10:11:12.5')
dt.second # => 12
dt.second_fraction # => (1/2)

This gem approaches second fraction using floats:

dt ='2014-05-06T10:11:12.5')
dt.second # => 12.5

Unmatching precison is handled strongly. Notice the time fragment is lost in DateTime.parse without warning only if the loose precision is in the time component.'2014-05-06T101112')  # => ISO8601::Errors::UnknownPattern
DateTime.parse('2014-05-06T101112')  # => #<DateTime: 2014-05-06T00:00:00+00:00 ((2456784j,0s,0n),+0s,2299161j)>'20140506T10:11:12')  # => ISO8601::Errors::UnknownPattern
DateTime.parse('20140506T10:11:12')  # => #<DateTime: 2014-05-06T10:11:12+00:00 ((2456784j,0s,0n),+0s,2299161j)>

DateTime#to_a allow decomposing to an array of atoms:

atoms ='2014-05-31T10:11:12Z').to_a # => [2014, 5, 31, 10, 11, 12, '+00:00']
dt =*atoms)

Ordinal dates keep the sign. 2014-001 is not the same as -2014-001.

Week dates raise an error when two digit days provied instead of return monday:'2014-W15-02') # => ISO8601::Errors::UnknownPattern'2014-W15-02')  # => #<Date: 2014-04-07 ((2456755j,0s,0n),+0s,2299161j)>



# Install a Ruby flavour
$ bundle install
$ bundle exec rspec

Docker (experimental)

This way is in an early stage so for now it's only possible to test one Ruby version (currently Ruby 2.2.)

# Install Docker
$ make build
$ make run

Vagrant (experimental)

This way is in an early stage so for now it's only possible to test one Ruby version (currently Ruby 2.2.)

# Install Vagrant and Virtualbox
$ vagrant up mri-2.2



  1. Fork it (
  2. Create your feature branch (git checkout -b features/xyz)
  3. Commit your changes (git commit -am 'Add XYZ')
  4. Push to the branch (git push origin features/xyz)
  5. Create new Pull Request


Arnau Siches under the MIT License

Something went wrong with that request. Please try again.