Project

General

Profile

Actions

Bug #21199

closed

Psych.dump and load on Date before 1582-10-15

Added by fitmap (Justin Peal) 5 days ago. Updated 4 days ago.

Status:
Third Party's Issue
Assignee:
-
Target version:
-
ruby -v:
ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x64-mingw-ucrt]
[ruby-core:121448]

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.

Actions #2

Updated by byroot (Jean Boussier) 5 days ago

  • Description updated (diff)

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.

Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0