Class: ActiveSupport::Duration::ISO8601Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/active_support/duration/iso8601_parser.rb

Overview

Parses a string formatted according to ISO 8601 Duration into the hash.

See ISO 8601 for more information.

This parser allows negative parts to be present in pattern.

Defined Under Namespace

Classes: ParsingError

Constant Summary collapse

PERIOD_OR_COMMA =
/\.|,/
PERIOD =
'.'.freeze
COMMA =
','.freeze
SIGN_MARKER =
/\A\-|\+|/
DATE_MARKER =
/P/
TIME_MARKER =
/T/
DATE_COMPONENT =
/(\-?\d+(?:[.,]\d+)?)(Y|M|D|W)/
TIME_COMPONENT =
/(\-?\d+(?:[.,]\d+)?)(H|M|S)/
DATE_TO_PART =
{ 'Y' => :years, 'M' => :months, 'W' => :weeks, 'D' => :days }
TIME_TO_PART =
{ 'H' => :hours, 'M' => :minutes, 'S' => :seconds }
DATE_COMPONENTS =
[:years, :months, :days]
TIME_COMPONENTS =
[:hours, :minutes, :seconds]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string) ⇒ ISO8601Parser

Returns a new instance of ISO8601Parser.



32
33
34
35
36
37
# File 'lib/active_support/duration/iso8601_parser.rb', line 32

def initialize(string)
  @scanner = StringScanner.new(string)
  @parts = {}
  @mode = :start
  @sign = 1
end

Instance Attribute Details

#modeObject

Returns the value of attribute mode.



30
31
32
# File 'lib/active_support/duration/iso8601_parser.rb', line 30

def mode
  @mode
end

#partsObject (readonly)

Returns the value of attribute parts.



29
30
31
# File 'lib/active_support/duration/iso8601_parser.rb', line 29

def parts
  @parts
end

#scannerObject (readonly)

Returns the value of attribute scanner.



29
30
31
# File 'lib/active_support/duration/iso8601_parser.rb', line 29

def scanner
  @scanner
end

#signObject

Returns the value of attribute sign.



30
31
32
# File 'lib/active_support/duration/iso8601_parser.rb', line 30

def sign
  @sign
end

Instance Method Details

#parse!Object



39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/active_support/duration/iso8601_parser.rb', line 39

def parse!
  while !finished?
    case mode
      when :start
        if scan(SIGN_MARKER)
          self.sign = (scanner.matched == '-') ? -1 : 1
          self.mode = :sign
        else
          raise_parsing_error
        end

      when :sign
        if scan(DATE_MARKER)
          self.mode = :date
        else
          raise_parsing_error
        end

      when :date
        if scan(TIME_MARKER)
          self.mode = :time
        elsif scan(DATE_COMPONENT)
          parts[DATE_TO_PART[scanner[2]]] = number * sign
        else
          raise_parsing_error
        end

      when :time
        if scan(TIME_COMPONENT)
          parts[TIME_TO_PART[scanner[2]]] = number * sign
        else
          raise_parsing_error
        end

    end
  end

  validate!
  parts
end