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.



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

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

Instance Attribute Details

#modeObject

Returns the value of attribute mode.



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

def mode
  @mode
end

#partsObject (readonly)

Returns the value of attribute parts.



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

def parts
  @parts
end

#scannerObject (readonly)

Returns the value of attribute scanner.



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

def scanner
  @scanner
end

#signObject

Returns the value of attribute sign.



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

def sign
  @sign
end

Instance Method Details

#parse!Object



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
79
# File 'lib/active_support/duration/iso8601_parser.rb', line 40

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