Skip to content

Commit

Permalink
Dump Date/DateTime as proleptic Gregorian date as well as Time
Browse files Browse the repository at this point in the history
Fix #572
  • Loading branch information
nobu committed Aug 9, 2022
1 parent 2366075 commit 9230426
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 10 deletions.
2 changes: 1 addition & 1 deletion lib/psych/scalar_scanner.rb
Expand Up @@ -63,7 +63,7 @@ def tokenize string
elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/)
require 'date'
begin
class_loader.date.strptime(string, '%Y-%m-%d')
class_loader.date.strptime(string, '%F', Date::GREGORIAN)
rescue ArgumentError
string
end
Expand Down
4 changes: 3 additions & 1 deletion lib/psych/visitors/to_ruby.rb
Expand Up @@ -80,7 +80,9 @@ def deserialize o
when "!ruby/object:DateTime"
class_loader.date_time
require 'date' unless defined? DateTime
@ss.parse_time(o.value).to_datetime
t = @ss.parse_time(o.value)
DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) +
(t.subsec/86400)
when '!ruby/encoding'
::Encoding.find o.value
when "!ruby/object:Complex"
Expand Down
16 changes: 8 additions & 8 deletions lib/psych/visitors/yaml_tree.rb
Expand Up @@ -192,12 +192,13 @@ def visit_Regexp o
register o, @emitter.scalar(o.inspect, nil, '!ruby/regexp', false, false, Nodes::Scalar::ANY)
end

def visit_Date o
register o, visit_Integer(o.gregorian)
end

def visit_DateTime o
formatted = if o.offset.zero?
o.strftime("%Y-%m-%d %H:%M:%S.%9N Z".freeze)
else
o.strftime("%Y-%m-%d %H:%M:%S.%9N %:z".freeze)
end
t = o.italy
formatted = format_time t, t.offset.zero?
tag = '!ruby/object:DateTime'
register o, @emitter.scalar(formatted, nil, tag, false, false, Nodes::Scalar::ANY)
end
Expand Down Expand Up @@ -235,7 +236,6 @@ def visit_Integer o
end
alias :visit_TrueClass :visit_Integer
alias :visit_FalseClass :visit_Integer
alias :visit_Date :visit_Integer

def visit_Float o
if o.nan?
Expand Down Expand Up @@ -482,8 +482,8 @@ def dump_exception o, msg
@emitter.end_mapping
end

def format_time time
if time.utc?
def format_time time, utc = time.utc?
if utc
time.strftime("%Y-%m-%d %H:%M:%S.%9N Z")
else
time.strftime("%Y-%m-%d %H:%M:%S.%9N %:z")
Expand Down
20 changes: 20 additions & 0 deletions test/psych/test_date_time.rb
Expand Up @@ -44,6 +44,26 @@ def test_datetime_timezone_offset
assert_match(/12:00:00-05:00/, cycled.last.to_s)
end

def test_julian_date
d = Date.new(1582, 10, 4, Date::GREGORIAN)
assert_cycle d
end

def test_proleptic_gregorian_date
d = Date.new(1582, 10, 14, Date::GREGORIAN)
assert_cycle d
end

def test_julian_datetime
dt = DateTime.new(1582, 10, 4, 23, 58, 59, 0, Date::GREGORIAN)
assert_cycle dt
end

def test_proleptic_gregorian_datetime
dt = DateTime.new(1582, 10, 14, 23, 58, 59, 0, Date::GREGORIAN)
assert_cycle dt
end

def test_invalid_date
assert_cycle "2013-10-31T10:40:07-000000000000033"
end
Expand Down

0 comments on commit 9230426

Please sign in to comment.