Bug #21199
closedPsych.dump and load on Date before 1582-10-15
Description
The code is:
require 'date'
require 'psych'
date = Date.new(1582, 10, 4)
p "date=#{date.inspect}"
str = Psych.dump(date, permitted_classes: [Date])
p "str=#{str}"
date2 = Psych.load(str, permitted_classes: [Date])
p "date2=#{date2.inspect}"
The output is:
"date=#<Date: 1582-10-04 ((2299160j,0s,0n),+0s,2299161j)>"
"str=--- 1582-10-14\n"
"date2=#<Date: 1582-10-14 ((2299160j,0s,0n),+0s,-Infj)>"
Updated by mame (Yusuke Endoh) 5 days ago
- Status changed from Open to Feedback
Note that date
and date2
are equal in your reproduction code.
require 'date'
require 'psych'
date = Date.new(1582, 10, 4)
p "date=#{date.inspect}"
str = Psych.dump(date, permitted_classes: [Date])
p "str=#{str}"
date2 = Psych.load(str, permitted_classes: [Date])
p "date2=#{date2.inspect}"
p date == date2 #=> true
The issue is that YAML cannot retain calendar information.
When Psych serializes a Date
object, it converts it to Date::GREGORIAN
(the proleptic Gregorian calendar).
As a result, the serialized YAML contains --- 1582-10-14
, which is intentional.
When deserializing a Date
from YAML, a Date::GREGORIAN
Date object is generated.
I believe it would be possible to convert it to an Date::ITALY
Date object by default.
However, consider a case where a user manually writes --- 1582-10-14
in YAML and loads it with Psych.
They would then get Date.new(1582, 10, 4)
, which could be an unexpected result.
For this reason, I thinkg the current behavior is unavoidable.
If you have a specific proposal on how to fix it, please write it.
Updated by fitmap (Justin Peal) 4 days ago
I suggest Psych.dump and Psych.load should deal the date as the default style Date::ITALY, like Date.new.
Normal people only know Date::ITALY, which skip 1582-10-05~1582-10-14.
I also suggest Date.to_s should convert inner date style to Date::ITALY, then output it.
'''
require 'date'
require 'psych'
date1 = Date.new(1582, 10, 4)
str = Psych.dump(date1, permitted_classes: [Date])
date2 = Psych.load(str, permitted_classes: [Date])
puts "date1=#{date1}, After dump and load, date2=#{date2}"
'''
date1=1582-10-04, After dump and load, date2=1582-10-14
Updated by nobu (Nobuyoshi Nakada) 4 days ago
- Status changed from Feedback to Third Party's Issue
- Backport changed from 3.1: UNKNOWN, 3.2: UNKNOWN, 3.3: UNKNOWN, 3.4: UNKNOWN to 3.1: DONTNEED, 3.2: DONTNEED, 3.3: DONTNEED, 3.4: DONTNEED
YAML has no specification of calendar systems.
If YAML specifies it, we would obey it of course.
Until then, YAML is not suitable for such dates, just don't use such dates.