setGregorianChange(new Date(Long.MIN_VALUE)) 不会将日历转换为纯 GregorianCalendar

setGregorianChange(new Date(Long.MIN_VALUE)) does not convert the calendar to pure GregorianCalendar

GregorianCalendar test= new GregorianCalendar();
BigDecimal coef=new BigDecimal(-2113480800);
test.setGregorianChange(new Date(Long.MIN_VALUE));
test.set(Calendar.DAY_OF_MONTH, 31);
test.set(Calendar.MONTH, 11);
test.set(Calendar.YEAR, 1600);
test.add(Calendar.DAY_OF_MONTH,-583657);
System.out.println((test.getTime()));

// I should get Jan 1 0003 but i get 03 jan 0003 OFFSET of 2 

您使用的日历很好 - 您只需要记住 Date 存储一个瞬间。它不记得日历、时区或文本格式。

您得到的 Date 值是正确的 - 它的纪元为 -62072462953058,对应于 0003-01-01T17:10:46Z(至少对我而言 - 取决于时间你 运行 代码)在一个不使用公历变化的系统中。

但是,Date.toString() 格式化那个瞬间,就好像 公历变化,导致两天的偏移。

您可以使用 Java 8 的 Instant 来查看:

import java.time.*;
import java.util.*;

public class Test {
    public static void main (String args[]) {
        GregorianCalendar test = new GregorianCalendar();
        test.setGregorianChange(new Date(Long.MIN_VALUE));
        test.set(Calendar.DAY_OF_MONTH, 31);
        test.set(Calendar.MONTH, 11);
        test.set(Calendar.YEAR, 1600);
        test.add(Calendar.DAY_OF_MONTH,-583657);
        Date date = test.getTime();
        Instant instant = Instant.ofEpochMilli(date.getTime());
        System.out.println(date);
        System.out.println(instant);
    }
}

输出(目前在伦敦):

Wed Jan 03 17:15:26 GMT 3
0003-01-01T17:15:26.913Z

这两个值表示相同的时间点,但是 Instant 到字符串的转换不会执行 Julian/Gregorian 转换,而 Date 会。