Class: KDL::Types::Duration::ISO8601Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/kdl/types/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 =
'.'
COMMA =
','
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 =
%i[years months days]
TIME_COMPONENTS =
%i[hours minutes seconds]

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(string) ⇒ ISO8601Parser

Returns a new instance of ISO8601Parser.



56
57
58
59
60
61
# File 'lib/kdl/types/duration/iso8601_parser.rb', line 56

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

Instance Attribute Details

#modeObject

Returns the value of attribute mode.



54
55
56
# File 'lib/kdl/types/duration/iso8601_parser.rb', line 54

def mode
  @mode
end

#partsObject (readonly)

Returns the value of attribute parts.



53
54
55
# File 'lib/kdl/types/duration/iso8601_parser.rb', line 53

def parts
  @parts
end

#scannerObject (readonly)

Returns the value of attribute scanner.



53
54
55
# File 'lib/kdl/types/duration/iso8601_parser.rb', line 53

def scanner
  @scanner
end

#signObject

Returns the value of attribute sign.



54
55
56
# File 'lib/kdl/types/duration/iso8601_parser.rb', line 54

def sign
  @sign
end

Instance Method Details

#parse!Object



63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/kdl/types/duration/iso8601_parser.rb', line 63

def parse!
  until 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