arturop-chronic_duration 0.9.7
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/Gemfile +10 -0
 - data/Gemfile.lock +30 -0
 - data/MIT-LICENSE +22 -0
 - data/README.rdoc +61 -0
 - data/Rakefile +45 -0
 - data/VERSION +1 -0
 - data/chronic_duration.gemspec +63 -0
 - data/lib/chronic_duration.rb +258 -0
 - data/spec/chronic_duration_spec.rb +200 -0
 - metadata +153 -0
 
    
        data/Gemfile
    ADDED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | 
         @@ -0,0 +1,30 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            GEM
         
     | 
| 
      
 2 
     | 
    
         
            +
              remote: http://rubygems.org/
         
     | 
| 
      
 3 
     | 
    
         
            +
              specs:
         
     | 
| 
      
 4 
     | 
    
         
            +
                diff-lcs (1.1.2)
         
     | 
| 
      
 5 
     | 
    
         
            +
                git (1.2.5)
         
     | 
| 
      
 6 
     | 
    
         
            +
                jeweler (1.5.2)
         
     | 
| 
      
 7 
     | 
    
         
            +
                  bundler (~> 1.0.0)
         
     | 
| 
      
 8 
     | 
    
         
            +
                  git (>= 1.2.5)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  rake
         
     | 
| 
      
 10 
     | 
    
         
            +
                numerizer (0.1.1)
         
     | 
| 
      
 11 
     | 
    
         
            +
                rake (0.8.7)
         
     | 
| 
      
 12 
     | 
    
         
            +
                rcov (0.9.9)
         
     | 
| 
      
 13 
     | 
    
         
            +
                rspec (2.3.0)
         
     | 
| 
      
 14 
     | 
    
         
            +
                  rspec-core (~> 2.3.0)
         
     | 
| 
      
 15 
     | 
    
         
            +
                  rspec-expectations (~> 2.3.0)
         
     | 
| 
      
 16 
     | 
    
         
            +
                  rspec-mocks (~> 2.3.0)
         
     | 
| 
      
 17 
     | 
    
         
            +
                rspec-core (2.3.1)
         
     | 
| 
      
 18 
     | 
    
         
            +
                rspec-expectations (2.3.0)
         
     | 
| 
      
 19 
     | 
    
         
            +
                  diff-lcs (~> 1.1.2)
         
     | 
| 
      
 20 
     | 
    
         
            +
                rspec-mocks (2.3.0)
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
            PLATFORMS
         
     | 
| 
      
 23 
     | 
    
         
            +
              ruby
         
     | 
| 
      
 24 
     | 
    
         
            +
             
     | 
| 
      
 25 
     | 
    
         
            +
            DEPENDENCIES
         
     | 
| 
      
 26 
     | 
    
         
            +
              bundler (~> 1.0.0)
         
     | 
| 
      
 27 
     | 
    
         
            +
              jeweler (~> 1.5.2)
         
     | 
| 
      
 28 
     | 
    
         
            +
              numerizer (~> 0.1.1)
         
     | 
| 
      
 29 
     | 
    
         
            +
              rcov
         
     | 
| 
      
 30 
     | 
    
         
            +
              rspec (~> 2.3.0)
         
     | 
    
        data/MIT-LICENSE
    ADDED
    
    | 
         @@ -0,0 +1,22 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            Copyright (c) Henry Poydar
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            Permission is hereby granted, free of charge, to any person
         
     | 
| 
      
 4 
     | 
    
         
            +
            obtaining a copy of this software and associated documentation
         
     | 
| 
      
 5 
     | 
    
         
            +
            files (the "Software"), to deal in the Software without
         
     | 
| 
      
 6 
     | 
    
         
            +
            restriction, including without limitation the rights to use,
         
     | 
| 
      
 7 
     | 
    
         
            +
            copy, modify, merge, publish, distribute, sublicense, and/or sell
         
     | 
| 
      
 8 
     | 
    
         
            +
            copies of the Software, and to permit persons to whom the
         
     | 
| 
      
 9 
     | 
    
         
            +
            Software is furnished to do so, subject to the following
         
     | 
| 
      
 10 
     | 
    
         
            +
            conditions:
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            The above copyright notice and this permission notice shall be
         
     | 
| 
      
 13 
     | 
    
         
            +
            included in all copies or substantial portions of the Software.
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
         
     | 
| 
      
 16 
     | 
    
         
            +
            EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
         
     | 
| 
      
 17 
     | 
    
         
            +
            OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
         
     | 
| 
      
 18 
     | 
    
         
            +
            NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
         
     | 
| 
      
 19 
     | 
    
         
            +
            HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
         
     | 
| 
      
 20 
     | 
    
         
            +
            WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
         
     | 
| 
      
 21 
     | 
    
         
            +
            FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
         
     | 
| 
      
 22 
     | 
    
         
            +
            OTHER DEALINGS IN THE SOFTWARE.
         
     | 
    
        data/README.rdoc
    ADDED
    
    | 
         @@ -0,0 +1,61 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            = Chronic Duration
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            A simple Ruby natural language parser for elapsed time. (For example, 4 hours and 30 minutes, 6 minutes 4 seconds, 3 days, etc.) Returns all results in seconds. Will return an integer unless you get tricky and need a float. (4 minutes and 13.47 seconds, for example.) 
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
            The reverse can also be accomplished with the output method.  So pass in seconds and you can get strings like 4 mins 31.51 secs (default  format), 4h 3m 30s, or 4:01:29.
         
     | 
| 
      
 6 
     | 
    
         
            +
             
     | 
| 
      
 7 
     | 
    
         
            +
            == Installation
         
     | 
| 
      
 8 
     | 
    
         
            +
             
     | 
| 
      
 9 
     | 
    
         
            +
                $ sudo gem sources -a http://gemcutter.org
         
     | 
| 
      
 10 
     | 
    
         
            +
                $ sudo gem install chronic_duration
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            == Usage
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                >> require 'chronic_duration'
         
     | 
| 
      
 15 
     | 
    
         
            +
                => true
         
     | 
| 
      
 16 
     | 
    
         
            +
                >> ChronicDuration.parse('4 minutes and 30 seconds')
         
     | 
| 
      
 17 
     | 
    
         
            +
                => 270
         
     | 
| 
      
 18 
     | 
    
         
            +
                >> ChronicDuration.output(270)
         
     | 
| 
      
 19 
     | 
    
         
            +
                => 4 mins 30 secs
         
     | 
| 
      
 20 
     | 
    
         
            +
                >> ChronicDuration.output(270, :format => :short)
         
     | 
| 
      
 21 
     | 
    
         
            +
                => 4m 30s
         
     | 
| 
      
 22 
     | 
    
         
            +
                >> ChronicDuration.output(270, :format => :long)
         
     | 
| 
      
 23 
     | 
    
         
            +
                => 4 minutes 30 seconds
         
     | 
| 
      
 24 
     | 
    
         
            +
                >> ChronicDuration.output(270, :format => :chrono)
         
     | 
| 
      
 25 
     | 
    
         
            +
                => 4:30
         
     | 
| 
      
 26 
     | 
    
         
            +
                
         
     | 
| 
      
 27 
     | 
    
         
            +
            Nil is returned if the string can't be parsed
         
     | 
| 
      
 28 
     | 
    
         
            +
             
     | 
| 
      
 29 
     | 
    
         
            +
            Examples of parse-able strings:
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
            * '12.4 secs'
         
     | 
| 
      
 32 
     | 
    
         
            +
            * '1:20' 
         
     | 
| 
      
 33 
     | 
    
         
            +
            * '1:20.51'
         
     | 
| 
      
 34 
     | 
    
         
            +
            * '4:01:01'
         
     | 
| 
      
 35 
     | 
    
         
            +
            * '3 mins 4 sec'
         
     | 
| 
      
 36 
     | 
    
         
            +
            * '2 hrs 20 min'
         
     | 
| 
      
 37 
     | 
    
         
            +
            * '2h20min'
         
     | 
| 
      
 38 
     | 
    
         
            +
            * '6 mos 1 day'
         
     | 
| 
      
 39 
     | 
    
         
            +
            * '47 yrs 6 mos and 4d'
         
     | 
| 
      
 40 
     | 
    
         
            +
            * 'two hours and twenty minutes'
         
     | 
| 
      
 41 
     | 
    
         
            +
            * '3 weeks and 2 days'
         
     | 
| 
      
 42 
     | 
    
         
            +
             
     | 
| 
      
 43 
     | 
    
         
            +
            ChronicDuration.raise_exceptions can be set to true to raise exceptions when the string can't be parsed.
         
     | 
| 
      
 44 
     | 
    
         
            +
             
     | 
| 
      
 45 
     | 
    
         
            +
                >> ChronicDuration.raise_exceptions = true
         
     | 
| 
      
 46 
     | 
    
         
            +
                => true
         
     | 
| 
      
 47 
     | 
    
         
            +
                >> ChronicDuration.parse('4 elephants and 3 Astroids')
         
     | 
| 
      
 48 
     | 
    
         
            +
                ChronicDuration::DurationParseError: An invalid word "elephants" was used in the string to be parsed.
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                
         
     | 
| 
      
 51 
     | 
    
         
            +
            == Contributors
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
            brianjlandau, jduff, olauzon, roboman, ianlevesque
         
     | 
| 
      
 54 
     | 
    
         
            +
                
         
     | 
| 
      
 55 
     | 
    
         
            +
            == TODO
         
     | 
| 
      
 56 
     | 
    
         
            +
             
     | 
| 
      
 57 
     | 
    
         
            +
            * Benchmark, optimize
         
     | 
| 
      
 58 
     | 
    
         
            +
            * Context specific matching (E.g., for '4m30s', assume 'm' is minutes not months)
         
     | 
| 
      
 59 
     | 
    
         
            +
            * Smartly parse vacation-like durations (E.g., '4 days and 3 nights')
         
     | 
| 
      
 60 
     | 
    
         
            +
            * :chrono output option should probably change to something like 4 days 4:00:12 instead of 4:04:00:12
         
     | 
| 
      
 61 
     | 
    
         
            +
            * Other locale support
         
     | 
    
        data/Rakefile
    ADDED
    
    | 
         @@ -0,0 +1,45 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'rubygems'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'bundler'
         
     | 
| 
      
 3 
     | 
    
         
            +
            begin
         
     | 
| 
      
 4 
     | 
    
         
            +
              Bundler.setup(:default, :development)
         
     | 
| 
      
 5 
     | 
    
         
            +
            rescue Bundler::BundlerError => e
         
     | 
| 
      
 6 
     | 
    
         
            +
              $stderr.puts e.message
         
     | 
| 
      
 7 
     | 
    
         
            +
              $stderr.puts "Run `bundle install` to install missing gems"
         
     | 
| 
      
 8 
     | 
    
         
            +
              exit e.status_code
         
     | 
| 
      
 9 
     | 
    
         
            +
            end
         
     | 
| 
      
 10 
     | 
    
         
            +
            require 'rake'
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
            require 'jeweler'
         
     | 
| 
      
 13 
     | 
    
         
            +
            Jeweler::Tasks.new do |gem|
         
     | 
| 
      
 14 
     | 
    
         
            +
              gem.name = "arturop-chronic_duration"
         
     | 
| 
      
 15 
     | 
    
         
            +
              gem.summary = %Q{A Ruby natural language parser for elapsed time}
         
     | 
| 
      
 16 
     | 
    
         
            +
              gem.license = "MIT"
         
     | 
| 
      
 17 
     | 
    
         
            +
              gem.description = %Q{A simple Ruby natural language parser for elapsed time. (For example, 4 hours and 30 minutes, 6 minutes 4 seconds, 3 days, etc.) Returns all results in seconds. Will return an integer unless you get tricky and need a float. (4 minutes and 13.47 seconds, for example.) The reverse can also be performed via the output method.}
         
     | 
| 
      
 18 
     | 
    
         
            +
              gem.email = "hpoydar@gmail.com"
         
     | 
| 
      
 19 
     | 
    
         
            +
              gem.homepage = "http://github.com/hpoydar/chronic_duration"
         
     | 
| 
      
 20 
     | 
    
         
            +
              gem.authors = ["hpoydar", "Arturo Pie"]
         
     | 
| 
      
 21 
     | 
    
         
            +
            end
         
     | 
| 
      
 22 
     | 
    
         
            +
            Jeweler::RubygemsDotOrgTasks.new
         
     | 
| 
      
 23 
     | 
    
         
            +
             
     | 
| 
      
 24 
     | 
    
         
            +
            require 'rspec/core'
         
     | 
| 
      
 25 
     | 
    
         
            +
            require 'rspec/core/rake_task'
         
     | 
| 
      
 26 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:spec) do |spec|
         
     | 
| 
      
 27 
     | 
    
         
            +
              spec.pattern = FileList['spec/**/*_spec.rb']
         
     | 
| 
      
 28 
     | 
    
         
            +
            end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
            RSpec::Core::RakeTask.new(:rcov) do |spec|
         
     | 
| 
      
 31 
     | 
    
         
            +
              spec.pattern = 'spec/**/*_spec.rb'
         
     | 
| 
      
 32 
     | 
    
         
            +
              spec.rcov = true
         
     | 
| 
      
 33 
     | 
    
         
            +
            end
         
     | 
| 
      
 34 
     | 
    
         
            +
             
     | 
| 
      
 35 
     | 
    
         
            +
            task :default => :spec
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
            require 'rake/rdoctask'
         
     | 
| 
      
 38 
     | 
    
         
            +
            Rake::RDocTask.new do |rdoc|
         
     | 
| 
      
 39 
     | 
    
         
            +
              version = File.exist?('VERSION') ? File.read('VERSION') : ""
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
              rdoc.rdoc_dir = 'rdoc'
         
     | 
| 
      
 42 
     | 
    
         
            +
              rdoc.title = "chronic_duration #{version}"
         
     | 
| 
      
 43 
     | 
    
         
            +
              rdoc.rdoc_files.include('README*')
         
     | 
| 
      
 44 
     | 
    
         
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         
     | 
| 
      
 45 
     | 
    
         
            +
            end
         
     | 
    
        data/VERSION
    ADDED
    
    | 
         @@ -0,0 +1 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            0.9.7
         
     | 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # Generated by jeweler
         
     | 
| 
      
 2 
     | 
    
         
            +
            # DO NOT EDIT THIS FILE DIRECTLY
         
     | 
| 
      
 3 
     | 
    
         
            +
            # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
         
     | 
| 
      
 4 
     | 
    
         
            +
            # -*- encoding: utf-8 -*-
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
            Gem::Specification.new do |s|
         
     | 
| 
      
 7 
     | 
    
         
            +
              s.name = %q{chronic_duration}
         
     | 
| 
      
 8 
     | 
    
         
            +
              s.version = "0.9.7"
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         
     | 
| 
      
 11 
     | 
    
         
            +
              s.authors = ["hpoydar", "Arturo Pie"]
         
     | 
| 
      
 12 
     | 
    
         
            +
              s.date = %q{2011-07-06}
         
     | 
| 
      
 13 
     | 
    
         
            +
              s.description = %q{A simple Ruby natural language parser for elapsed time. (For example, 4 hours and 30 minutes, 6 minutes 4 seconds, 3 days, etc.) Returns all results in seconds. Will return an integer unless you get tricky and need a float. (4 minutes and 13.47 seconds, for example.) The reverse can also be performed via the output method.}
         
     | 
| 
      
 14 
     | 
    
         
            +
              s.email = %q{hpoydar@gmail.com}
         
     | 
| 
      
 15 
     | 
    
         
            +
              s.extra_rdoc_files = [
         
     | 
| 
      
 16 
     | 
    
         
            +
                "README.rdoc"
         
     | 
| 
      
 17 
     | 
    
         
            +
              ]
         
     | 
| 
      
 18 
     | 
    
         
            +
              s.files = [
         
     | 
| 
      
 19 
     | 
    
         
            +
                "Gemfile",
         
     | 
| 
      
 20 
     | 
    
         
            +
                "Gemfile.lock",
         
     | 
| 
      
 21 
     | 
    
         
            +
                "MIT-LICENSE",
         
     | 
| 
      
 22 
     | 
    
         
            +
                "README.rdoc",
         
     | 
| 
      
 23 
     | 
    
         
            +
                "Rakefile",
         
     | 
| 
      
 24 
     | 
    
         
            +
                "VERSION",
         
     | 
| 
      
 25 
     | 
    
         
            +
                "chronic_duration.gemspec",
         
     | 
| 
      
 26 
     | 
    
         
            +
                "lib/chronic_duration.rb",
         
     | 
| 
      
 27 
     | 
    
         
            +
                "spec/chronic_duration_spec.rb"
         
     | 
| 
      
 28 
     | 
    
         
            +
              ]
         
     | 
| 
      
 29 
     | 
    
         
            +
              s.homepage = %q{http://github.com/hpoydar/chronic_duration}
         
     | 
| 
      
 30 
     | 
    
         
            +
              s.licenses = ["MIT"]
         
     | 
| 
      
 31 
     | 
    
         
            +
              s.require_paths = ["lib"]
         
     | 
| 
      
 32 
     | 
    
         
            +
              s.rubygems_version = %q{1.3.7}
         
     | 
| 
      
 33 
     | 
    
         
            +
              s.summary = %q{A Ruby natural language parser for elapsed time}
         
     | 
| 
      
 34 
     | 
    
         
            +
              s.test_files = [
         
     | 
| 
      
 35 
     | 
    
         
            +
                "spec/chronic_duration_spec.rb"
         
     | 
| 
      
 36 
     | 
    
         
            +
              ]
         
     | 
| 
      
 37 
     | 
    
         
            +
             
     | 
| 
      
 38 
     | 
    
         
            +
              if s.respond_to? :specification_version then
         
     | 
| 
      
 39 
     | 
    
         
            +
                current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
         
     | 
| 
      
 40 
     | 
    
         
            +
                s.specification_version = 3
         
     | 
| 
      
 41 
     | 
    
         
            +
             
     | 
| 
      
 42 
     | 
    
         
            +
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         
     | 
| 
      
 43 
     | 
    
         
            +
                  s.add_runtime_dependency(%q<numerizer>, ["~> 0.1.1"])
         
     | 
| 
      
 44 
     | 
    
         
            +
                  s.add_development_dependency(%q<rspec>, ["~> 2.3.0"])
         
     | 
| 
      
 45 
     | 
    
         
            +
                  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
         
     | 
| 
      
 46 
     | 
    
         
            +
                  s.add_development_dependency(%q<jeweler>, ["~> 1.5.2"])
         
     | 
| 
      
 47 
     | 
    
         
            +
                  s.add_development_dependency(%q<rcov>, [">= 0"])
         
     | 
| 
      
 48 
     | 
    
         
            +
                else
         
     | 
| 
      
 49 
     | 
    
         
            +
                  s.add_dependency(%q<numerizer>, ["~> 0.1.1"])
         
     | 
| 
      
 50 
     | 
    
         
            +
                  s.add_dependency(%q<rspec>, ["~> 2.3.0"])
         
     | 
| 
      
 51 
     | 
    
         
            +
                  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         
     | 
| 
      
 52 
     | 
    
         
            +
                  s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
         
     | 
| 
      
 53 
     | 
    
         
            +
                  s.add_dependency(%q<rcov>, [">= 0"])
         
     | 
| 
      
 54 
     | 
    
         
            +
                end
         
     | 
| 
      
 55 
     | 
    
         
            +
              else
         
     | 
| 
      
 56 
     | 
    
         
            +
                s.add_dependency(%q<numerizer>, ["~> 0.1.1"])
         
     | 
| 
      
 57 
     | 
    
         
            +
                s.add_dependency(%q<rspec>, ["~> 2.3.0"])
         
     | 
| 
      
 58 
     | 
    
         
            +
                s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         
     | 
| 
      
 59 
     | 
    
         
            +
                s.add_dependency(%q<jeweler>, ["~> 1.5.2"])
         
     | 
| 
      
 60 
     | 
    
         
            +
                s.add_dependency(%q<rcov>, [">= 0"])
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
         @@ -0,0 +1,258 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'numerizer' unless defined?(Numerizer)
         
     | 
| 
      
 2 
     | 
    
         
            +
            module ChronicDuration
         
     | 
| 
      
 3 
     | 
    
         
            +
              extend self
         
     | 
| 
      
 4 
     | 
    
         
            +
             
     | 
| 
      
 5 
     | 
    
         
            +
              class DurationParseError < StandardError
         
     | 
| 
      
 6 
     | 
    
         
            +
              end
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
              @@raise_exceptions = false
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
              def self.raise_exceptions
         
     | 
| 
      
 11 
     | 
    
         
            +
                !!@@raise_exceptions
         
     | 
| 
      
 12 
     | 
    
         
            +
              end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
              def self.raise_exceptions=(value)
         
     | 
| 
      
 15 
     | 
    
         
            +
                @@raise_exceptions = !!value
         
     | 
| 
      
 16 
     | 
    
         
            +
              end
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
              # Given a string representation of elapsed time,
         
     | 
| 
      
 19 
     | 
    
         
            +
              # return an integer (or float, if fractions of a
         
     | 
| 
      
 20 
     | 
    
         
            +
              # second are input)
         
     | 
| 
      
 21 
     | 
    
         
            +
              def parse(string, opts = {})
         
     | 
| 
      
 22 
     | 
    
         
            +
                result = calculate_from_words(cleanup(string), opts)
         
     | 
| 
      
 23 
     | 
    
         
            +
                result == 0 ? nil : result
         
     | 
| 
      
 24 
     | 
    
         
            +
              end
         
     | 
| 
      
 25 
     | 
    
         
            +
             
     | 
| 
      
 26 
     | 
    
         
            +
              # Given an integer and an optional format,
         
     | 
| 
      
 27 
     | 
    
         
            +
              # returns a formatted string representing elapsed time
         
     | 
| 
      
 28 
     | 
    
         
            +
              def output(seconds, opts = {})
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                opts[:format] ||= :default
         
     | 
| 
      
 31 
     | 
    
         
            +
                unit_of_measures = [:years, :months, :days, :hours, :minutes]
         
     | 
| 
      
 32 
     | 
    
         
            +
                unit_of_measures << :seconds unless opts[:hide_seconds]
         
     | 
| 
      
 33 
     | 
    
         
            +
             
     | 
| 
      
 34 
     | 
    
         
            +
                duration = Duration.new seconds
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                joiner = ' '
         
     | 
| 
      
 37 
     | 
    
         
            +
                process = nil
         
     | 
| 
      
 38 
     | 
    
         
            +
             
     | 
| 
      
 39 
     | 
    
         
            +
                case opts[:format]
         
     | 
| 
      
 40 
     | 
    
         
            +
                when :micro
         
     | 
| 
      
 41 
     | 
    
         
            +
                  dividers = {
         
     | 
| 
      
 42 
     | 
    
         
            +
                    :years => 'y', :months => 'm', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
         
     | 
| 
      
 43 
     | 
    
         
            +
                  joiner = ''
         
     | 
| 
      
 44 
     | 
    
         
            +
                when :short
         
     | 
| 
      
 45 
     | 
    
         
            +
                  dividers = {
         
     | 
| 
      
 46 
     | 
    
         
            +
                    :years => 'y', :months => 'm', :days => 'd', :hours => 'h', :minutes => 'm', :seconds => 's' }
         
     | 
| 
      
 47 
     | 
    
         
            +
                when :default
         
     | 
| 
      
 48 
     | 
    
         
            +
                  dividers = {
         
     | 
| 
      
 49 
     | 
    
         
            +
                    :years => ' yr', :months => ' mo', :days => ' day', :hours => ' hr', :minutes => ' min', :seconds => ' sec',
         
     | 
| 
      
 50 
     | 
    
         
            +
                    :pluralize => true }
         
     | 
| 
      
 51 
     | 
    
         
            +
                when :long
         
     | 
| 
      
 52 
     | 
    
         
            +
                  dividers = {
         
     | 
| 
      
 53 
     | 
    
         
            +
                    :years => ' year', :months => ' month', :days => ' day', :hours => ' hour', :minutes => ' minute', :seconds => ' second',
         
     | 
| 
      
 54 
     | 
    
         
            +
                    :pluralize => true }
         
     | 
| 
      
 55 
     | 
    
         
            +
                when :chrono
         
     | 
| 
      
 56 
     | 
    
         
            +
                  dividers = {
         
     | 
| 
      
 57 
     | 
    
         
            +
                    :years => ':', :months => ':', :days => ':', :hours => ':', :minutes => ':', :seconds => ':', :keep_zero => true }
         
     | 
| 
      
 58 
     | 
    
         
            +
                  process = lambda do |str|
         
     | 
| 
      
 59 
     | 
    
         
            +
                    # Pad zeros
         
     | 
| 
      
 60 
     | 
    
         
            +
                    # Get rid of lead off times if they are zero
         
     | 
| 
      
 61 
     | 
    
         
            +
                    # Get rid of lead off zero
         
     | 
| 
      
 62 
     | 
    
         
            +
                    # Get rid of trailing :
         
     | 
| 
      
 63 
     | 
    
         
            +
                    str.gsub(/\b\d\b/) { |d| ("%02d" % d) }.gsub(/^(00:)+/, '').gsub(/^0/, '').gsub(/:$/, '')
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  joiner = ''
         
     | 
| 
      
 66 
     | 
    
         
            +
                end
         
     | 
| 
      
 67 
     | 
    
         
            +
             
     | 
| 
      
 68 
     | 
    
         
            +
                result = []
         
     | 
| 
      
 69 
     | 
    
         
            +
                unit_of_measures.each do |t|
         
     | 
| 
      
 70 
     | 
    
         
            +
                  num = duration.send t
         
     | 
| 
      
 71 
     | 
    
         
            +
                  num = ("%.#{decimal_places seconds }f" % num) if num.is_a?(Float) && t == :seconds
         
     | 
| 
      
 72 
     | 
    
         
            +
                  result << humanize_time_unit( num, dividers[t], dividers[:pluralize], dividers[:keep_zero] )
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                result = result.join(joiner).squeeze(' ').strip
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                if process
         
     | 
| 
      
 78 
     | 
    
         
            +
                  result = process.call(result)
         
     | 
| 
      
 79 
     | 
    
         
            +
                end
         
     | 
| 
      
 80 
     | 
    
         
            +
             
     | 
| 
      
 81 
     | 
    
         
            +
                result.length == 0 ? nil : result
         
     | 
| 
      
 82 
     | 
    
         
            +
             
     | 
| 
      
 83 
     | 
    
         
            +
              end
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
              def decimal_places number
         
     | 
| 
      
 86 
     | 
    
         
            +
                number.to_s.split('.').last.length if number.is_a? Float
         
     | 
| 
      
 87 
     | 
    
         
            +
              end
         
     | 
| 
      
 88 
     | 
    
         
            +
             
     | 
| 
      
 89 
     | 
    
         
            +
              class Duration
         
     | 
| 
      
 90 
     | 
    
         
            +
                attr_accessor :seconds, :minutes, :hours, :days, :months, :years
         
     | 
| 
      
 91 
     | 
    
         
            +
             
     | 
| 
      
 92 
     | 
    
         
            +
                def initialize seconds
         
     | 
| 
      
 93 
     | 
    
         
            +
                  @years = @months = @days = @hours = @minutes = 0
         
     | 
| 
      
 94 
     | 
    
         
            +
                  @seconds = seconds
         
     | 
| 
      
 95 
     | 
    
         
            +
             
     | 
| 
      
 96 
     | 
    
         
            +
                  compute_measures seconds
         
     | 
| 
      
 97 
     | 
    
         
            +
                end
         
     | 
| 
      
 98 
     | 
    
         
            +
             
     | 
| 
      
 99 
     | 
    
         
            +
                private
         
     | 
| 
      
 100 
     | 
    
         
            +
                def compute_measures seconds
         
     | 
| 
      
 101 
     | 
    
         
            +
                  quotient = seconds
         
     | 
| 
      
 102 
     | 
    
         
            +
                  remainder = 0
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
                  unit_of_measures.each do |uom|
         
     | 
| 
      
 105 
     | 
    
         
            +
                    break unless quotient > uom[:amount]
         
     | 
| 
      
 106 
     | 
    
         
            +
                    remainder = quotient % uom[:amount]
         
     | 
| 
      
 107 
     | 
    
         
            +
                    quotient /= uom[:amount]
         
     | 
| 
      
 108 
     | 
    
         
            +
                    assign uom[:name], remainder
         
     | 
| 
      
 109 
     | 
    
         
            +
                    assign uom[:parent], quotient.to_i
         
     | 
| 
      
 110 
     | 
    
         
            +
                  end
         
     | 
| 
      
 111 
     | 
    
         
            +
                end
         
     | 
| 
      
 112 
     | 
    
         
            +
             
     | 
| 
      
 113 
     | 
    
         
            +
                def unit_of_measures
         
     | 
| 
      
 114 
     | 
    
         
            +
                  [ { :name => :seconds=, :parent => :minutes=, :amount => 60 },
         
     | 
| 
      
 115 
     | 
    
         
            +
                    { :name => :minutes=, :parent => :hours=, :amount => 60 },
         
     | 
| 
      
 116 
     | 
    
         
            +
                    { :name => :hours=, :parent => :days=, :amount => 24 },
         
     | 
| 
      
 117 
     | 
    
         
            +
                    { :name => :days=, :parent => :months=, :amount => 30 },
         
     | 
| 
      
 118 
     | 
    
         
            +
                    { :name => :months=, :parent => :years=, :amount => 12 }
         
     | 
| 
      
 119 
     | 
    
         
            +
                  ]
         
     | 
| 
      
 120 
     | 
    
         
            +
                end
         
     | 
| 
      
 121 
     | 
    
         
            +
             
     | 
| 
      
 122 
     | 
    
         
            +
                def assign setter, value
         
     | 
| 
      
 123 
     | 
    
         
            +
                  self.send setter, value
         
     | 
| 
      
 124 
     | 
    
         
            +
                end
         
     | 
| 
      
 125 
     | 
    
         
            +
              end
         
     | 
| 
      
 126 
     | 
    
         
            +
            private
         
     | 
| 
      
 127 
     | 
    
         
            +
             
     | 
| 
      
 128 
     | 
    
         
            +
              def humanize_time_unit(number, unit, pluralize, keep_zero)
         
     | 
| 
      
 129 
     | 
    
         
            +
                return '' if number == 0 && !keep_zero
         
     | 
| 
      
 130 
     | 
    
         
            +
                res = "#{number}#{unit}"
         
     | 
| 
      
 131 
     | 
    
         
            +
                # A poor man's pluralizer
         
     | 
| 
      
 132 
     | 
    
         
            +
                res << 's' if !(number == 1) && pluralize
         
     | 
| 
      
 133 
     | 
    
         
            +
                res
         
     | 
| 
      
 134 
     | 
    
         
            +
              end
         
     | 
| 
      
 135 
     | 
    
         
            +
             
     | 
| 
      
 136 
     | 
    
         
            +
              def calculate_from_words(string, opts)
         
     | 
| 
      
 137 
     | 
    
         
            +
                val = 0
         
     | 
| 
      
 138 
     | 
    
         
            +
                words = string.split(' ')
         
     | 
| 
      
 139 
     | 
    
         
            +
                words.each_with_index do |v, k|
         
     | 
| 
      
 140 
     | 
    
         
            +
                  if v =~ float_matcher
         
     | 
| 
      
 141 
     | 
    
         
            +
                    val += (convert_to_number(v) * duration_units_seconds_multiplier(words[k + 1] || (opts[:default_unit] || 'seconds')))
         
     | 
| 
      
 142 
     | 
    
         
            +
                  end
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
      
 144 
     | 
    
         
            +
                val
         
     | 
| 
      
 145 
     | 
    
         
            +
              end
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
              def cleanup(string)
         
     | 
| 
      
 148 
     | 
    
         
            +
                res = string.downcase
         
     | 
| 
      
 149 
     | 
    
         
            +
                res = filter_by_type(Numerizer.numerize(res))
         
     | 
| 
      
 150 
     | 
    
         
            +
                res = res.gsub(float_matcher) {|n| " #{n} "}.squeeze(' ').strip
         
     | 
| 
      
 151 
     | 
    
         
            +
                res = filter_through_white_list(res)
         
     | 
| 
      
 152 
     | 
    
         
            +
              end
         
     | 
| 
      
 153 
     | 
    
         
            +
             
     | 
| 
      
 154 
     | 
    
         
            +
              def convert_to_number(string)
         
     | 
| 
      
 155 
     | 
    
         
            +
                string.to_f % 1 > 0 ? string.to_f : string.to_i
         
     | 
| 
      
 156 
     | 
    
         
            +
              end
         
     | 
| 
      
 157 
     | 
    
         
            +
             
     | 
| 
      
 158 
     | 
    
         
            +
              def duration_units_list
         
     | 
| 
      
 159 
     | 
    
         
            +
                %w(seconds minutes hours days weeks months years)
         
     | 
| 
      
 160 
     | 
    
         
            +
              end
         
     | 
| 
      
 161 
     | 
    
         
            +
              def duration_units_seconds_multiplier(unit)
         
     | 
| 
      
 162 
     | 
    
         
            +
                return 0 unless duration_units_list.include?(unit)
         
     | 
| 
      
 163 
     | 
    
         
            +
                case unit
         
     | 
| 
      
 164 
     | 
    
         
            +
                when 'years';   31536000 # doesn't accounts for leap years
         
     | 
| 
      
 165 
     | 
    
         
            +
                when 'months';  3600 * 24 * 30
         
     | 
| 
      
 166 
     | 
    
         
            +
                when 'weeks';   3600 * 24 * 7
         
     | 
| 
      
 167 
     | 
    
         
            +
                when 'days';    3600 * 24
         
     | 
| 
      
 168 
     | 
    
         
            +
                when 'hours';   3600
         
     | 
| 
      
 169 
     | 
    
         
            +
                when 'minutes'; 60
         
     | 
| 
      
 170 
     | 
    
         
            +
                when 'seconds'; 1
         
     | 
| 
      
 171 
     | 
    
         
            +
                end
         
     | 
| 
      
 172 
     | 
    
         
            +
              end
         
     | 
| 
      
 173 
     | 
    
         
            +
             
     | 
| 
      
 174 
     | 
    
         
            +
              def error_message
         
     | 
| 
      
 175 
     | 
    
         
            +
                'Sorry, that duration could not be parsed'
         
     | 
| 
      
 176 
     | 
    
         
            +
              end
         
     | 
| 
      
 177 
     | 
    
         
            +
             
     | 
| 
      
 178 
     | 
    
         
            +
              # Parse 3:41:59 and return 3 hours 41 minutes 59 seconds
         
     | 
| 
      
 179 
     | 
    
         
            +
              def filter_by_type(string)
         
     | 
| 
      
 180 
     | 
    
         
            +
                if string.gsub(' ', '') =~ /#{float_matcher}(:#{float_matcher})+/
         
     | 
| 
      
 181 
     | 
    
         
            +
                  res = []
         
     | 
| 
      
 182 
     | 
    
         
            +
                  string.gsub(' ', '').split(':').reverse.each_with_index do |v,k|
         
     | 
| 
      
 183 
     | 
    
         
            +
                    return unless duration_units_list[k]
         
     | 
| 
      
 184 
     | 
    
         
            +
                    res << "#{v} #{duration_units_list[k]}"
         
     | 
| 
      
 185 
     | 
    
         
            +
                  end
         
     | 
| 
      
 186 
     | 
    
         
            +
                  res = res.reverse.join(' ')
         
     | 
| 
      
 187 
     | 
    
         
            +
                else
         
     | 
| 
      
 188 
     | 
    
         
            +
                  res = string
         
     | 
| 
      
 189 
     | 
    
         
            +
                end
         
     | 
| 
      
 190 
     | 
    
         
            +
                res
         
     | 
| 
      
 191 
     | 
    
         
            +
              end
         
     | 
| 
      
 192 
     | 
    
         
            +
             
     | 
| 
      
 193 
     | 
    
         
            +
              def float_matcher
         
     | 
| 
      
 194 
     | 
    
         
            +
                /[0-9]*\.?[0-9]+/
         
     | 
| 
      
 195 
     | 
    
         
            +
              end
         
     | 
| 
      
 196 
     | 
    
         
            +
             
     | 
| 
      
 197 
     | 
    
         
            +
              # Get rid of unknown words and map found
         
     | 
| 
      
 198 
     | 
    
         
            +
              # words to defined time units
         
     | 
| 
      
 199 
     | 
    
         
            +
              def filter_through_white_list(string)
         
     | 
| 
      
 200 
     | 
    
         
            +
                res = []
         
     | 
| 
      
 201 
     | 
    
         
            +
                string.split(' ').each do |word|
         
     | 
| 
      
 202 
     | 
    
         
            +
                  if word =~ float_matcher
         
     | 
| 
      
 203 
     | 
    
         
            +
                    res << word.strip
         
     | 
| 
      
 204 
     | 
    
         
            +
                    next
         
     | 
| 
      
 205 
     | 
    
         
            +
                  end
         
     | 
| 
      
 206 
     | 
    
         
            +
                  stripped_word = word.strip.gsub(/^,/, '').gsub(/,$/, '')
         
     | 
| 
      
 207 
     | 
    
         
            +
                  if mappings.has_key?(stripped_word)
         
     | 
| 
      
 208 
     | 
    
         
            +
                    res << mappings[stripped_word]
         
     | 
| 
      
 209 
     | 
    
         
            +
                  elsif !join_words.include?(stripped_word) and ChronicDuration.raise_exceptions
         
     | 
| 
      
 210 
     | 
    
         
            +
                    raise DurationParseError, "An invalid word #{word.inspect} was used in the string to be parsed."
         
     | 
| 
      
 211 
     | 
    
         
            +
                  end
         
     | 
| 
      
 212 
     | 
    
         
            +
                end
         
     | 
| 
      
 213 
     | 
    
         
            +
                res.join(' ')
         
     | 
| 
      
 214 
     | 
    
         
            +
              end
         
     | 
| 
      
 215 
     | 
    
         
            +
             
     | 
| 
      
 216 
     | 
    
         
            +
              def mappings
         
     | 
| 
      
 217 
     | 
    
         
            +
                {
         
     | 
| 
      
 218 
     | 
    
         
            +
                  'seconds' => 'seconds',
         
     | 
| 
      
 219 
     | 
    
         
            +
                  'second'  => 'seconds',
         
     | 
| 
      
 220 
     | 
    
         
            +
                  'secs'    => 'seconds',
         
     | 
| 
      
 221 
     | 
    
         
            +
                  'sec'     => 'seconds',
         
     | 
| 
      
 222 
     | 
    
         
            +
                  's'       => 'seconds',
         
     | 
| 
      
 223 
     | 
    
         
            +
                  'minutes' => 'minutes',
         
     | 
| 
      
 224 
     | 
    
         
            +
                  'minute'  => 'minutes',
         
     | 
| 
      
 225 
     | 
    
         
            +
                  'mins'    => 'minutes',
         
     | 
| 
      
 226 
     | 
    
         
            +
                  'min'     => 'minutes',
         
     | 
| 
      
 227 
     | 
    
         
            +
                  'm'       => 'minutes',
         
     | 
| 
      
 228 
     | 
    
         
            +
                  'hours'   => 'hours',
         
     | 
| 
      
 229 
     | 
    
         
            +
                  'hour'    => 'hours',
         
     | 
| 
      
 230 
     | 
    
         
            +
                  'hrs'     => 'hours',
         
     | 
| 
      
 231 
     | 
    
         
            +
                  'hr'      => 'hours',
         
     | 
| 
      
 232 
     | 
    
         
            +
                  'h'       => 'hours',
         
     | 
| 
      
 233 
     | 
    
         
            +
                  'days'    => 'days',
         
     | 
| 
      
 234 
     | 
    
         
            +
                  'day'     => 'days',
         
     | 
| 
      
 235 
     | 
    
         
            +
                  'dy'      => 'days',
         
     | 
| 
      
 236 
     | 
    
         
            +
                  'd'       => 'days',
         
     | 
| 
      
 237 
     | 
    
         
            +
                  'weeks'   => 'weeks',
         
     | 
| 
      
 238 
     | 
    
         
            +
                  'week'    => 'weeks',
         
     | 
| 
      
 239 
     | 
    
         
            +
                  'w'       => 'weeks',
         
     | 
| 
      
 240 
     | 
    
         
            +
                  'months'  => 'months',
         
     | 
| 
      
 241 
     | 
    
         
            +
                  'mos'     => 'months',
         
     | 
| 
      
 242 
     | 
    
         
            +
                  'month'   => 'months',
         
     | 
| 
      
 243 
     | 
    
         
            +
                  'years'   => 'years',
         
     | 
| 
      
 244 
     | 
    
         
            +
                  'year'    => 'years',
         
     | 
| 
      
 245 
     | 
    
         
            +
                  'yrs'     => 'years',
         
     | 
| 
      
 246 
     | 
    
         
            +
                  'y'       => 'years'
         
     | 
| 
      
 247 
     | 
    
         
            +
                }
         
     | 
| 
      
 248 
     | 
    
         
            +
              end
         
     | 
| 
      
 249 
     | 
    
         
            +
             
     | 
| 
      
 250 
     | 
    
         
            +
              def join_words
         
     | 
| 
      
 251 
     | 
    
         
            +
                ['and', 'with', 'plus']
         
     | 
| 
      
 252 
     | 
    
         
            +
              end
         
     | 
| 
      
 253 
     | 
    
         
            +
             
     | 
| 
      
 254 
     | 
    
         
            +
              def white_list
         
     | 
| 
      
 255 
     | 
    
         
            +
                self.mappings.map {|k, v| k}
         
     | 
| 
      
 256 
     | 
    
         
            +
              end
         
     | 
| 
      
 257 
     | 
    
         
            +
             
     | 
| 
      
 258 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,200 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'chronic_duration'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe ChronicDuration, '.parse' do
         
     | 
| 
      
 4 
     | 
    
         
            +
              
         
     | 
| 
      
 5 
     | 
    
         
            +
              @exemplars = { 
         
     | 
| 
      
 6 
     | 
    
         
            +
                '1:20'                  => 60 + 20,
         
     | 
| 
      
 7 
     | 
    
         
            +
                '1:20.51'               => 60 + 20.51,
         
     | 
| 
      
 8 
     | 
    
         
            +
                '4:01:01'               => 4 * 3600 + 60 + 1,
         
     | 
| 
      
 9 
     | 
    
         
            +
                '3 mins 4 sec'          => 3 * 60 + 4,
         
     | 
| 
      
 10 
     | 
    
         
            +
                '3 Mins 4 Sec'          => 3 * 60 + 4,
         
     | 
| 
      
 11 
     | 
    
         
            +
                'three mins four sec'          => 3 * 60 + 4,
         
     | 
| 
      
 12 
     | 
    
         
            +
                '2 hrs 20 min'          => 2 * 3600 + 20 * 60,
         
     | 
| 
      
 13 
     | 
    
         
            +
                '2h20min'               => 2 * 3600 + 20 * 60,
         
     | 
| 
      
 14 
     | 
    
         
            +
                '6 mos 1 day'           => 6 * 30 * 24 * 3600 + 24 * 3600,
         
     | 
| 
      
 15 
     | 
    
         
            +
                '1 year 6 mos 1 day'    => 1 * 31536000 + 6 * 30 * 24 * 3600 + 24 * 3600,
         
     | 
| 
      
 16 
     | 
    
         
            +
                '2.5 hrs'               => 2.5 * 3600,
         
     | 
| 
      
 17 
     | 
    
         
            +
                '47 yrs 6 mos and 4.5d' => 47 * 31536000 + 6 * 30 * 24 * 3600 + 4.5 * 24 * 3600,
         
     | 
| 
      
 18 
     | 
    
         
            +
                'two hours and twenty minutes' => 2 * 3600 + 20 * 60,
         
     | 
| 
      
 19 
     | 
    
         
            +
                'four hours and forty minutes' => 4 * 3600 + 40 * 60,
         
     | 
| 
      
 20 
     | 
    
         
            +
                'four hours, and fourty minutes' => 4 * 3600 + 40 * 60,
         
     | 
| 
      
 21 
     | 
    
         
            +
                '3 weeks and, 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
         
     | 
| 
      
 22 
     | 
    
         
            +
                '3 weeks, plus 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
         
     | 
| 
      
 23 
     | 
    
         
            +
                '3 weeks with 2 days' => 3600 * 24 * 7 * 3 + 3600 * 24 * 2,
         
     | 
| 
      
 24 
     | 
    
         
            +
                '1 month'               => 3600 * 24 * 30,
         
     | 
| 
      
 25 
     | 
    
         
            +
                '2 months'              => 3600 * 24 * 30 * 2
         
     | 
| 
      
 26 
     | 
    
         
            +
              }
         
     | 
| 
      
 27 
     | 
    
         
            +
              
         
     | 
| 
      
 28 
     | 
    
         
            +
              it "should return nil if the string can't be parsed" do
         
     | 
| 
      
 29 
     | 
    
         
            +
                ChronicDuration.parse('gobblygoo').should be_nil
         
     | 
| 
      
 30 
     | 
    
         
            +
              end
         
     | 
| 
      
 31 
     | 
    
         
            +
              
         
     | 
| 
      
 32 
     | 
    
         
            +
              it "should raise an exception if the string can't be parsed and @@raise_exceptions is set to true" do
         
     | 
| 
      
 33 
     | 
    
         
            +
                ChronicDuration.raise_exceptions = true
         
     | 
| 
      
 34 
     | 
    
         
            +
                lambda { ChronicDuration.parse('23 gobblygoos') }.should raise_exception(ChronicDuration::DurationParseError)
         
     | 
| 
      
 35 
     | 
    
         
            +
                ChronicDuration.raise_exceptions = false
         
     | 
| 
      
 36 
     | 
    
         
            +
              end
         
     | 
| 
      
 37 
     | 
    
         
            +
              
         
     | 
| 
      
 38 
     | 
    
         
            +
              it "should return a float if seconds are in decimals" do
         
     | 
| 
      
 39 
     | 
    
         
            +
                ChronicDuration.parse('12 mins 3.141 seconds').is_a?(Float).should be_true
         
     | 
| 
      
 40 
     | 
    
         
            +
              end
         
     | 
| 
      
 41 
     | 
    
         
            +
              
         
     | 
| 
      
 42 
     | 
    
         
            +
              it "should return an integer unless the seconds are in decimals" do
         
     | 
| 
      
 43 
     | 
    
         
            +
                ChronicDuration.parse('12 mins 3 seconds').is_a?(Integer).should be_true
         
     | 
| 
      
 44 
     | 
    
         
            +
              end
         
     | 
| 
      
 45 
     | 
    
         
            +
              
         
     | 
| 
      
 46 
     | 
    
         
            +
              it "should be able to parse minutes by default" do
         
     | 
| 
      
 47 
     | 
    
         
            +
                ChronicDuration.parse('5', :default_unit => "minutes").should == 300
         
     | 
| 
      
 48 
     | 
    
         
            +
              end
         
     | 
| 
      
 49 
     | 
    
         
            +
              
         
     | 
| 
      
 50 
     | 
    
         
            +
              @exemplars.each do |k, v|
         
     | 
| 
      
 51 
     | 
    
         
            +
                it "should properly parse a duration like #{k}" do
         
     | 
| 
      
 52 
     | 
    
         
            +
                  ChronicDuration.parse(k).should == v
         
     | 
| 
      
 53 
     | 
    
         
            +
                end
         
     | 
| 
      
 54 
     | 
    
         
            +
              end
         
     | 
| 
      
 55 
     | 
    
         
            +
              
         
     | 
| 
      
 56 
     | 
    
         
            +
            end
         
     | 
| 
      
 57 
     | 
    
         
            +
             
     | 
| 
      
 58 
     | 
    
         
            +
            describe ChronicDuration, '.output' do
         
     | 
| 
      
 59 
     | 
    
         
            +
              
         
     | 
| 
      
 60 
     | 
    
         
            +
              it "should return nil if the input can't be parsed" do
         
     | 
| 
      
 61 
     | 
    
         
            +
                ChronicDuration.parse('gobblygoo').should be_nil
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
             
     | 
| 
      
 64 
     | 
    
         
            +
              def self.exemplars
         
     | 
| 
      
 65 
     | 
    
         
            +
                { 
         
     | 
| 
      
 66 
     | 
    
         
            +
                  #(0) => 
         
     | 
| 
      
 67 
     | 
    
         
            +
                  #{
         
     | 
| 
      
 68 
     | 
    
         
            +
                  #:micro    => '0s',
         
     | 
| 
      
 69 
     | 
    
         
            +
                  #:short    => '0s',
         
     | 
| 
      
 70 
     | 
    
         
            +
                  #:default  => '0 secs',
         
     | 
| 
      
 71 
     | 
    
         
            +
                  #:long     => '0 seconds',
         
     | 
| 
      
 72 
     | 
    
         
            +
                  #:chrono   => '0'
         
     | 
| 
      
 73 
     | 
    
         
            +
                  #},
         
     | 
| 
      
 74 
     | 
    
         
            +
                  (60 + 20) => 
         
     | 
| 
      
 75 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 76 
     | 
    
         
            +
                    :micro    => '1m20s',
         
     | 
| 
      
 77 
     | 
    
         
            +
                    :short    => '1m 20s',
         
     | 
| 
      
 78 
     | 
    
         
            +
                    :default  => '1 min 20 secs',
         
     | 
| 
      
 79 
     | 
    
         
            +
                    :long     => '1 minute 20 seconds',
         
     | 
| 
      
 80 
     | 
    
         
            +
                    :chrono   => '1:20'
         
     | 
| 
      
 81 
     | 
    
         
            +
                  },
         
     | 
| 
      
 82 
     | 
    
         
            +
                  (60 + 20.51) => 
         
     | 
| 
      
 83 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 84 
     | 
    
         
            +
                    :micro    => '1m20.51s',
         
     | 
| 
      
 85 
     | 
    
         
            +
                    :short    => '1m 20.51s',
         
     | 
| 
      
 86 
     | 
    
         
            +
                    :default  => '1 min 20.51 secs',
         
     | 
| 
      
 87 
     | 
    
         
            +
                    :long     => '1 minute 20.51 seconds',
         
     | 
| 
      
 88 
     | 
    
         
            +
                    :chrono   => '1:20.51'
         
     | 
| 
      
 89 
     | 
    
         
            +
                  },
         
     | 
| 
      
 90 
     | 
    
         
            +
                  (60 + 20.51928) => 
         
     | 
| 
      
 91 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 92 
     | 
    
         
            +
                    :micro    => '1m20.51928s',
         
     | 
| 
      
 93 
     | 
    
         
            +
                    :short    => '1m 20.51928s',
         
     | 
| 
      
 94 
     | 
    
         
            +
                    :default  => '1 min 20.51928 secs',
         
     | 
| 
      
 95 
     | 
    
         
            +
                    :long     => '1 minute 20.51928 seconds',
         
     | 
| 
      
 96 
     | 
    
         
            +
                    :chrono   => '1:20.51928'
         
     | 
| 
      
 97 
     | 
    
         
            +
                  },
         
     | 
| 
      
 98 
     | 
    
         
            +
                  (4 * 3600 + 60 + 1) => 
         
     | 
| 
      
 99 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 100 
     | 
    
         
            +
                    :micro    => '4h1m1s',
         
     | 
| 
      
 101 
     | 
    
         
            +
                    :short    => '4h 1m 1s',
         
     | 
| 
      
 102 
     | 
    
         
            +
                    :default  => '4 hrs 1 min 1 sec',
         
     | 
| 
      
 103 
     | 
    
         
            +
                    :long     => '4 hours 1 minute 1 second',
         
     | 
| 
      
 104 
     | 
    
         
            +
                    :chrono   => '4:01:01'
         
     | 
| 
      
 105 
     | 
    
         
            +
                  },
         
     | 
| 
      
 106 
     | 
    
         
            +
                  (2 * 3600 + 20 * 60) => 
         
     | 
| 
      
 107 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 108 
     | 
    
         
            +
                    :micro    => '2h20m',
         
     | 
| 
      
 109 
     | 
    
         
            +
                    :short    => '2h 20m',
         
     | 
| 
      
 110 
     | 
    
         
            +
                    :default  => '2 hrs 20 mins',
         
     | 
| 
      
 111 
     | 
    
         
            +
                    :long     => '2 hours 20 minutes',
         
     | 
| 
      
 112 
     | 
    
         
            +
                    :chrono   => '2:20'
         
     | 
| 
      
 113 
     | 
    
         
            +
                  },
         
     | 
| 
      
 114 
     | 
    
         
            +
                  (2 * 3600 + 20 * 60) => 
         
     | 
| 
      
 115 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 116 
     | 
    
         
            +
                    :micro    => '2h20m',
         
     | 
| 
      
 117 
     | 
    
         
            +
                    :short    => '2h 20m',
         
     | 
| 
      
 118 
     | 
    
         
            +
                    :default  => '2 hrs 20 mins',
         
     | 
| 
      
 119 
     | 
    
         
            +
                    :long     => '2 hours 20 minutes',
         
     | 
| 
      
 120 
     | 
    
         
            +
                    :chrono   => '2:20:00'
         
     | 
| 
      
 121 
     | 
    
         
            +
                  },
         
     | 
| 
      
 122 
     | 
    
         
            +
                  (6 * 30 * 24 * 3600 + 24 * 3600) => 
         
     | 
| 
      
 123 
     | 
    
         
            +
                  { 
         
     | 
| 
      
 124 
     | 
    
         
            +
                    :micro    => '6m1d',
         
     | 
| 
      
 125 
     | 
    
         
            +
                    :short    => '6m 1d',
         
     | 
| 
      
 126 
     | 
    
         
            +
                    :default  => '6 mos 1 day',
         
     | 
| 
      
 127 
     | 
    
         
            +
                    :long     => '6 months 1 day',
         
     | 
| 
      
 128 
     | 
    
         
            +
                    :chrono   => '6:01:00:00:00' # Yuck. FIXME
         
     | 
| 
      
 129 
     | 
    
         
            +
                  }
         
     | 
| 
      
 130 
     | 
    
         
            +
                }
         
     | 
| 
      
 131 
     | 
    
         
            +
              end
         
     | 
| 
      
 132 
     | 
    
         
            +
             
     | 
| 
      
 133 
     | 
    
         
            +
              exemplars.each do |number_seconds, test_cases|
         
     | 
| 
      
 134 
     | 
    
         
            +
                test_cases.each do |format, expected_output|
         
     | 
| 
      
 135 
     | 
    
         
            +
                  it "should properly output a duration of #{number_seconds} seconds as #{expected_output} using the #{format.to_s} format option" do
         
     | 
| 
      
 136 
     | 
    
         
            +
                    ChronicDuration.output(number_seconds, :format => format).should == expected_output
         
     | 
| 
      
 137 
     | 
    
         
            +
                  end
         
     | 
| 
      
 138 
     | 
    
         
            +
                end
         
     | 
| 
      
 139 
     | 
    
         
            +
              end
         
     | 
| 
      
 140 
     | 
    
         
            +
             
     | 
| 
      
 141 
     | 
    
         
            +
              context "using :hide_seconds" do
         
     | 
| 
      
 142 
     | 
    
         
            +
                it "should return nil if less than 60 seconds are passed" do
         
     | 
| 
      
 143 
     | 
    
         
            +
                  ChronicDuration.output(59, :hide_seconds => true).should be_nil
         
     | 
| 
      
 144 
     | 
    
         
            +
                end
         
     | 
| 
      
 145 
     | 
    
         
            +
             
     | 
| 
      
 146 
     | 
    
         
            +
                exemplars.each do |number_seconds, test_cases|
         
     | 
| 
      
 147 
     | 
    
         
            +
                  test_cases.each do |format, expected_output|
         
     | 
| 
      
 148 
     | 
    
         
            +
                    regex = (format == :chrono) ? /:\d\d\.?\d*$/ : /\ ?\d+\.?\d*\ ?(seconds*|secs*|s)/
         
     | 
| 
      
 149 
     | 
    
         
            +
                    expected_output_without_secs = expected_output.gsub(regex, "")
         
     | 
| 
      
 150 
     | 
    
         
            +
                    it "should properly output a duration of #{number_seconds} seconds as #{expected_output_without_secs} using the #{format.to_s} format option" do
         
     | 
| 
      
 151 
     | 
    
         
            +
                      ChronicDuration.output(number_seconds, :format => format, :hide_seconds => true).should == expected_output_without_secs
         
     | 
| 
      
 152 
     | 
    
         
            +
                    end
         
     | 
| 
      
 153 
     | 
    
         
            +
                  end
         
     | 
| 
      
 154 
     | 
    
         
            +
                end
         
     | 
| 
      
 155 
     | 
    
         
            +
              end
         
     | 
| 
      
 156 
     | 
    
         
            +
             
     | 
| 
      
 157 
     | 
    
         
            +
              it "should use the default format when the format is not specified" do
         
     | 
| 
      
 158 
     | 
    
         
            +
                ChronicDuration.output(2 * 3600 + 20 * 60).should == '2 hrs 20 mins'
         
     | 
| 
      
 159 
     | 
    
         
            +
              end
         
     | 
| 
      
 160 
     | 
    
         
            +
            end
         
     | 
| 
      
 161 
     | 
    
         
            +
             
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
            # Some of the private methods deserve some spec'ing to aid
         
     | 
| 
      
 164 
     | 
    
         
            +
            # us in development...
         
     | 
| 
      
 165 
     | 
    
         
            +
             
     | 
| 
      
 166 
     | 
    
         
            +
            describe ChronicDuration, "private methods" do
         
     | 
| 
      
 167 
     | 
    
         
            +
              
         
     | 
| 
      
 168 
     | 
    
         
            +
              describe ".filter_by_type" do
         
     | 
| 
      
 169 
     | 
    
         
            +
                
         
     | 
| 
      
 170 
     | 
    
         
            +
                it "should take a chrono-formatted time like 3:14 and return a human time like 3 minutes 14 seconds" do
         
     | 
| 
      
 171 
     | 
    
         
            +
                  ChronicDuration.instance_eval("filter_by_type('3:14')").should == '3 minutes 14 seconds'
         
     | 
| 
      
 172 
     | 
    
         
            +
                end
         
     | 
| 
      
 173 
     | 
    
         
            +
                
         
     | 
| 
      
 174 
     | 
    
         
            +
                it "should take a chrono-formatted time like 12:10:14 and return a human time like 12 hours 10 minutes 14 seconds" do
         
     | 
| 
      
 175 
     | 
    
         
            +
                  ChronicDuration.instance_eval("filter_by_type('12:10:14')").should == '12 hours 10 minutes 14 seconds'
         
     | 
| 
      
 176 
     | 
    
         
            +
                end
         
     | 
| 
      
 177 
     | 
    
         
            +
                
         
     | 
| 
      
 178 
     | 
    
         
            +
                it "should return the input if it's not a chrono-formatted time" do
         
     | 
| 
      
 179 
     | 
    
         
            +
                  ChronicDuration.instance_eval("filter_by_type('4 hours')").should == '4 hours'
         
     | 
| 
      
 180 
     | 
    
         
            +
                end
         
     | 
| 
      
 181 
     | 
    
         
            +
              
         
     | 
| 
      
 182 
     | 
    
         
            +
              end
         
     | 
| 
      
 183 
     | 
    
         
            +
              
         
     | 
| 
      
 184 
     | 
    
         
            +
              describe ".cleanup" do
         
     | 
| 
      
 185 
     | 
    
         
            +
                
         
     | 
| 
      
 186 
     | 
    
         
            +
                it "should clean up extraneous words" do
         
     | 
| 
      
 187 
     | 
    
         
            +
                  ChronicDuration.instance_eval("cleanup('4 days and 11 hours')").should == '4 days 11 hours'
         
     | 
| 
      
 188 
     | 
    
         
            +
                end
         
     | 
| 
      
 189 
     | 
    
         
            +
                
         
     | 
| 
      
 190 
     | 
    
         
            +
                it "should cleanup extraneous spaces" do
         
     | 
| 
      
 191 
     | 
    
         
            +
                  ChronicDuration.instance_eval("cleanup('  4 days and 11     hours')").should == '4 days 11 hours'
         
     | 
| 
      
 192 
     | 
    
         
            +
                end
         
     | 
| 
      
 193 
     | 
    
         
            +
                
         
     | 
| 
      
 194 
     | 
    
         
            +
                it "should insert spaces where there aren't any" do
         
     | 
| 
      
 195 
     | 
    
         
            +
                  ChronicDuration.instance_eval("cleanup('4m11.5s')").should == '4 minutes 11.5 seconds'
         
     | 
| 
      
 196 
     | 
    
         
            +
                end
         
     | 
| 
      
 197 
     | 
    
         
            +
                
         
     | 
| 
      
 198 
     | 
    
         
            +
              end
         
     | 
| 
      
 199 
     | 
    
         
            +
              
         
     | 
| 
      
 200 
     | 
    
         
            +
            end 
         
     | 
    
        metadata
    ADDED
    
    | 
         @@ -0,0 +1,153 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            --- !ruby/object:Gem::Specification 
         
     | 
| 
      
 2 
     | 
    
         
            +
            name: arturop-chronic_duration
         
     | 
| 
      
 3 
     | 
    
         
            +
            version: !ruby/object:Gem::Version 
         
     | 
| 
      
 4 
     | 
    
         
            +
              hash: 53
         
     | 
| 
      
 5 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 6 
     | 
    
         
            +
              segments: 
         
     | 
| 
      
 7 
     | 
    
         
            +
              - 0
         
     | 
| 
      
 8 
     | 
    
         
            +
              - 9
         
     | 
| 
      
 9 
     | 
    
         
            +
              - 7
         
     | 
| 
      
 10 
     | 
    
         
            +
              version: 0.9.7
         
     | 
| 
      
 11 
     | 
    
         
            +
            platform: ruby
         
     | 
| 
      
 12 
     | 
    
         
            +
            authors: 
         
     | 
| 
      
 13 
     | 
    
         
            +
            - hpoydar
         
     | 
| 
      
 14 
     | 
    
         
            +
            - Arturo Pie
         
     | 
| 
      
 15 
     | 
    
         
            +
            autorequire: 
         
     | 
| 
      
 16 
     | 
    
         
            +
            bindir: bin
         
     | 
| 
      
 17 
     | 
    
         
            +
            cert_chain: []
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
            date: 2011-07-06 00:00:00 -04:00
         
     | 
| 
      
 20 
     | 
    
         
            +
            default_executable: 
         
     | 
| 
      
 21 
     | 
    
         
            +
            dependencies: 
         
     | 
| 
      
 22 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 23 
     | 
    
         
            +
              version_requirements: &id001 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 24 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 25 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 26 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 27 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 28 
     | 
    
         
            +
                    hash: 25
         
     | 
| 
      
 29 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 30 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 31 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 32 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 33 
     | 
    
         
            +
                    version: 0.1.1
         
     | 
| 
      
 34 
     | 
    
         
            +
              requirement: *id001
         
     | 
| 
      
 35 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 36 
     | 
    
         
            +
              type: :runtime
         
     | 
| 
      
 37 
     | 
    
         
            +
              name: numerizer
         
     | 
| 
      
 38 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 39 
     | 
    
         
            +
              version_requirements: &id002 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 40 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 41 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 42 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 43 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 44 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 45 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 46 
     | 
    
         
            +
                    - 2
         
     | 
| 
      
 47 
     | 
    
         
            +
                    - 3
         
     | 
| 
      
 48 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 49 
     | 
    
         
            +
                    version: 2.3.0
         
     | 
| 
      
 50 
     | 
    
         
            +
              requirement: *id002
         
     | 
| 
      
 51 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 52 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 53 
     | 
    
         
            +
              name: rspec
         
     | 
| 
      
 54 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 55 
     | 
    
         
            +
              version_requirements: &id003 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 56 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 57 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 58 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 59 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 60 
     | 
    
         
            +
                    hash: 23
         
     | 
| 
      
 61 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 62 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 63 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 64 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 65 
     | 
    
         
            +
                    version: 1.0.0
         
     | 
| 
      
 66 
     | 
    
         
            +
              requirement: *id003
         
     | 
| 
      
 67 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 68 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 69 
     | 
    
         
            +
              name: bundler
         
     | 
| 
      
 70 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 71 
     | 
    
         
            +
              version_requirements: &id004 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 72 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 73 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 74 
     | 
    
         
            +
                - - ~>
         
     | 
| 
      
 75 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 76 
     | 
    
         
            +
                    hash: 7
         
     | 
| 
      
 77 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 78 
     | 
    
         
            +
                    - 1
         
     | 
| 
      
 79 
     | 
    
         
            +
                    - 5
         
     | 
| 
      
 80 
     | 
    
         
            +
                    - 2
         
     | 
| 
      
 81 
     | 
    
         
            +
                    version: 1.5.2
         
     | 
| 
      
 82 
     | 
    
         
            +
              requirement: *id004
         
     | 
| 
      
 83 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 84 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 85 
     | 
    
         
            +
              name: jeweler
         
     | 
| 
      
 86 
     | 
    
         
            +
            - !ruby/object:Gem::Dependency 
         
     | 
| 
      
 87 
     | 
    
         
            +
              version_requirements: &id005 !ruby/object:Gem::Requirement 
         
     | 
| 
      
 88 
     | 
    
         
            +
                none: false
         
     | 
| 
      
 89 
     | 
    
         
            +
                requirements: 
         
     | 
| 
      
 90 
     | 
    
         
            +
                - - ">="
         
     | 
| 
      
 91 
     | 
    
         
            +
                  - !ruby/object:Gem::Version 
         
     | 
| 
      
 92 
     | 
    
         
            +
                    hash: 3
         
     | 
| 
      
 93 
     | 
    
         
            +
                    segments: 
         
     | 
| 
      
 94 
     | 
    
         
            +
                    - 0
         
     | 
| 
      
 95 
     | 
    
         
            +
                    version: "0"
         
     | 
| 
      
 96 
     | 
    
         
            +
              requirement: *id005
         
     | 
| 
      
 97 
     | 
    
         
            +
              prerelease: false
         
     | 
| 
      
 98 
     | 
    
         
            +
              type: :development
         
     | 
| 
      
 99 
     | 
    
         
            +
              name: rcov
         
     | 
| 
      
 100 
     | 
    
         
            +
            description: A simple Ruby natural language parser for elapsed time. (For example, 4 hours and 30 minutes, 6 minutes 4 seconds, 3 days, etc.) Returns all results in seconds. Will return an integer unless you get tricky and need a float. (4 minutes and 13.47 seconds, for example.) The reverse can also be performed via the output method.
         
     | 
| 
      
 101 
     | 
    
         
            +
            email: hpoydar@gmail.com
         
     | 
| 
      
 102 
     | 
    
         
            +
            executables: []
         
     | 
| 
      
 103 
     | 
    
         
            +
             
     | 
| 
      
 104 
     | 
    
         
            +
            extensions: []
         
     | 
| 
      
 105 
     | 
    
         
            +
             
     | 
| 
      
 106 
     | 
    
         
            +
            extra_rdoc_files: 
         
     | 
| 
      
 107 
     | 
    
         
            +
            - README.rdoc
         
     | 
| 
      
 108 
     | 
    
         
            +
            files: 
         
     | 
| 
      
 109 
     | 
    
         
            +
            - Gemfile
         
     | 
| 
      
 110 
     | 
    
         
            +
            - Gemfile.lock
         
     | 
| 
      
 111 
     | 
    
         
            +
            - MIT-LICENSE
         
     | 
| 
      
 112 
     | 
    
         
            +
            - README.rdoc
         
     | 
| 
      
 113 
     | 
    
         
            +
            - Rakefile
         
     | 
| 
      
 114 
     | 
    
         
            +
            - VERSION
         
     | 
| 
      
 115 
     | 
    
         
            +
            - chronic_duration.gemspec
         
     | 
| 
      
 116 
     | 
    
         
            +
            - lib/chronic_duration.rb
         
     | 
| 
      
 117 
     | 
    
         
            +
            - spec/chronic_duration_spec.rb
         
     | 
| 
      
 118 
     | 
    
         
            +
            has_rdoc: true
         
     | 
| 
      
 119 
     | 
    
         
            +
            homepage: http://github.com/hpoydar/chronic_duration
         
     | 
| 
      
 120 
     | 
    
         
            +
            licenses: 
         
     | 
| 
      
 121 
     | 
    
         
            +
            - MIT
         
     | 
| 
      
 122 
     | 
    
         
            +
            post_install_message: 
         
     | 
| 
      
 123 
     | 
    
         
            +
            rdoc_options: []
         
     | 
| 
      
 124 
     | 
    
         
            +
             
     | 
| 
      
 125 
     | 
    
         
            +
            require_paths: 
         
     | 
| 
      
 126 
     | 
    
         
            +
            - lib
         
     | 
| 
      
 127 
     | 
    
         
            +
            required_ruby_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 128 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 129 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 130 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 131 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 132 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
      
 133 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 134 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 135 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 136 
     | 
    
         
            +
            required_rubygems_version: !ruby/object:Gem::Requirement 
         
     | 
| 
      
 137 
     | 
    
         
            +
              none: false
         
     | 
| 
      
 138 
     | 
    
         
            +
              requirements: 
         
     | 
| 
      
 139 
     | 
    
         
            +
              - - ">="
         
     | 
| 
      
 140 
     | 
    
         
            +
                - !ruby/object:Gem::Version 
         
     | 
| 
      
 141 
     | 
    
         
            +
                  hash: 3
         
     | 
| 
      
 142 
     | 
    
         
            +
                  segments: 
         
     | 
| 
      
 143 
     | 
    
         
            +
                  - 0
         
     | 
| 
      
 144 
     | 
    
         
            +
                  version: "0"
         
     | 
| 
      
 145 
     | 
    
         
            +
            requirements: []
         
     | 
| 
      
 146 
     | 
    
         
            +
             
     | 
| 
      
 147 
     | 
    
         
            +
            rubyforge_project: 
         
     | 
| 
      
 148 
     | 
    
         
            +
            rubygems_version: 1.3.7
         
     | 
| 
      
 149 
     | 
    
         
            +
            signing_key: 
         
     | 
| 
      
 150 
     | 
    
         
            +
            specification_version: 3
         
     | 
| 
      
 151 
     | 
    
         
            +
            summary: A Ruby natural language parser for elapsed time
         
     | 
| 
      
 152 
     | 
    
         
            +
            test_files: 
         
     | 
| 
      
 153 
     | 
    
         
            +
            - spec/chronic_duration_spec.rb
         
     |