Class: OfxParser::OfxParser

Inherits:
Object
  • Object
show all
Defined in:
lib/ofx-parser.rb

Class Method Summary collapse

Class Method Details

.parse(ofx) ⇒ Object

Creates and returns an Ofx instance when given a well-formed OFX document, complete with the mandatory key:pair header.



16
17
18
19
20
21
22
23
24
25
26
# File 'lib/ofx-parser.rb', line 16

def self.parse(ofx)
  ofx = ofx.respond_to?(:read) ? ofx.read.to_s : ofx.to_s

  return Ofx.new if ofx == ""

  header, body = pre_process(ofx)

  ofx_out = parse_body(body)
  ofx_out.header = header
  ofx_out
end

.parse_datetime(date) ⇒ Object

Takes an OFX datetime string of the format:

  • YYYYMMDDHHMMSS.XXX[gmt offset:tz name]

  • YYYYMMDD

  • YYYYMMDDHHMMSS

  • YYYYMMDDHHMMSS.XXX

Returns a DateTime object. Milliseconds (XXX) are ignored.



56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/ofx-parser.rb', line 56

def self.parse_datetime(date)
  if /\A\s*
      (\d{4})(\d{2})(\d{2})       ?# YYYYMMDD            1,2,3
      (?:(\d{2})(\d{2})(\d{2}))?  ?# HHMMSS  - optional  4,5,6
      (?:\.(\d{3}))?              ?# .XXX    - optional  7
      (?:\[(-?\d+)\:\w{3}\])?     ?# [-n:TZ] - optional  8,9
      \s*\z/ix =~ date
    year = $1.to_i
    mon = $2.to_i
    day = $3.to_i
    hour = $4.to_i
    min = $5.to_i
    sec = $6.to_i
    # DateTime does not support usecs.
    # usec = 0
    # usec = $7.to_f * 1000000 if $7
    off = Rational($8.to_i, 24) # offset as a fraction of day. :|
    DateTime.civil(year, mon, day, hour, min, sec, off)
  end
end

.pre_process(ofx) ⇒ Object

Designed to make the main OFX body parsable. This means adding closing tags to the SGML to make it parsable by hpricot.

Returns an array of 2 elements:

  • header as a hash,

  • body as an evily pre-processed string ready for parsing by hpricot.



34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/ofx-parser.rb', line 34

def self.pre_process(ofx)
  header, body = ofx.split(/\n{2,}|:?<OFX>/, 2)

  header = Hash[*header.gsub(/^\r?\n+/,'').split(/\r\n/).collect do |e| 
    e.split(/:/,2)
  end.flatten]

  body.gsub!(/>\s+</m, '><')
  body.gsub!(/\s+</m, '<')
  body.gsub!(/>\s+/m, '>')
  body.gsub!(/<(\w+?)>([^<]+)/m, '<\1>\2</\1>')

  [header, body]
end