diff options
-rw-r--r-- | lib/psych/scalar_scanner.rb | 7 | ||||
-rw-r--r-- | lib/psych/visitors/to_ruby.rb | 13 | ||||
-rw-r--r-- | test/test_scalar_scanner.rb | 11 | ||||
-rw-r--r-- | test/visitors/test_to_ruby.rb | 24 |
4 files changed, 54 insertions, 1 deletions
diff --git a/lib/psych/scalar_scanner.rb b/lib/psych/scalar_scanner.rb index 5a038a5..a15096f 100644 --- a/lib/psych/scalar_scanner.rb +++ b/lib/psych/scalar_scanner.rb @@ -4,6 +4,9 @@ module Psych ### # Scan scalars for built in types class ScalarScanner + # Taken from http://yaml.org/type/timestamp.html + TIME = /\d{4}-\d{1,2}-\d{1,2}([Tt]|\s+)\d{1,2}:\d\d:\d\d(\.\d*)?(\s*Z|[-+]\d{1,2}(:\d\d)?)?/ + def initialize string @string = string end @@ -12,7 +15,9 @@ module Psych return [:NULL, nil] if @string.empty? case @string - when /^\d{4}-\d{2}-\d{2}$/ + when TIME + [:TIME, @string] + when /^\d{4}-\d{1,2}-\d{1,2}$/ [:DATE, @string] when /^\.inf$/i [:POSITIVE_INFINITY, 1 / 0.0] diff --git a/lib/psych/visitors/to_ruby.rb b/lib/psych/visitors/to_ruby.rb index abdfd4c..b4e33ed 100644 --- a/lib/psych/visitors/to_ruby.rb +++ b/lib/psych/visitors/to_ruby.rb @@ -35,6 +35,19 @@ module Psych when :DATE require 'date' Date.strptime token.last, '%Y-%m-%d' + when :TIME + lexeme = token.last + + date, time = *(lexeme.split(/[ tT]/, 2)) + (yy, m, dd) = date.split('-').map { |x| x.to_i } + md = time.match /(\d+:\d+:\d+)(\.\d*)?\s*(Z|[-+]\d+(:\d\d)?)?/ + + (hh, mm, ss) = md[1].split(':').map { |x| x.to_i } + + time = Time.utc(yy, m, dd, hh, mm, ss) + + tz = (!md[3] || md[3] == 'Z') ? 0 : Integer(md[3].split(':').first) + Time.at((time - (tz * 3600)).to_i, md[2].sub(/^\./, '').to_i) else token.last end diff --git a/test/test_scalar_scanner.rb b/test/test_scalar_scanner.rb index c3b19aa..4e76082 100644 --- a/test/test_scalar_scanner.rb +++ b/test/test_scalar_scanner.rb @@ -2,6 +2,17 @@ require 'minitest/autorun' require 'psych' class TestScalarScanner < MiniTest::Unit::TestCase + def test_scan_time + [ '2001-12-15T02:59:43.1Z', + '2001-12-14t21:59:43.10-05:00', + '2001-12-14 21:59:43.10 -5', + '2001-12-15 2:59:43.10', + ].each do |time| + ss = Psych::ScalarScanner.new time + assert_equal :TIME, ss.tokenize.first + end + end + def test_scan_date date = '1980-12-16' ss = Psych::ScalarScanner.new date diff --git a/test/visitors/test_to_ruby.rb b/test/visitors/test_to_ruby.rb index c60a9b9..41eae48 100644 --- a/test/visitors/test_to_ruby.rb +++ b/test/visitors/test_to_ruby.rb @@ -11,6 +11,30 @@ module Psych @visitor = ToRuby.new end + def test_time + now = Time.now + formatted = now.strftime("%Y-%m-%d %H:%M:%S") + + ".%06d %d:00" % [now.usec, now.gmt_offset / 3600] + + assert_equal now, Nodes::Scalar.new(formatted).to_ruby + end + + def test_time_utc + now = Time.now.utc + formatted = now.strftime("%Y-%m-%d %H:%M:%S") + + ".%06dZ" % [now.usec] + + assert_equal now, Nodes::Scalar.new(formatted).to_ruby + end + + def test_time_utc_no_z + now = Time.now.utc + formatted = now.strftime("%Y-%m-%d %H:%M:%S") + + ".%06d" % [now.usec] + + assert_equal now, Nodes::Scalar.new(formatted).to_ruby + end + def test_date d = '1980-12-16' actual = Date.strptime(d, '%Y-%m-%d') |