热释光;医生:我在做手术时得到了一个奇怪的结果 GregorianCalendar
自定义julian->gregorian转换日期。1800年1月1日变为1800年1月12日,其中1800在自定义切换日期(1918年1月31日)之前,但在默认切换日期(1582年10月15日)之后(这不会在默认切换日期之前或在默认日历上发生。)
这是我想使用的更大算法的一部分 GregorianCalendar
为了计算一年中的某些日期,希望朱利安/公历闰年的计算对我来说是透明的,因为日期可能在转换日期之前或之后。
我正在尝试使用 GregorianCalendar
,引自gregoriancalendar api文档:
公历是一种混合历法,支持儒略和公历系统,支持单一的间断,默认情况下对应于公历建立时的公历日期(1582年10月15日在一些国家,后来在其他国家)。调用者可以通过调用setgregorianchange()来更改切换日期。
在公历转换之前,公历实行儒略历。公历和儒略历的唯一区别是闰年法则。
在公历建立之前,新年是3月25日。为避免混淆,此日历始终使用1月1日。
为了复制基本问题,这里有一个基本的java main()
方法。我创建了两个日历,一个是默认的公历,另一个是公历,上面写着俄罗斯采用它时的转换日期,即1918年1月31日。然后我把两个日历都设为1800年1月1日。“俄罗斯”日历将这一日期改为1800年1月12日,如设置后立即打印出来时所示。
public static void main(String[] args) {
DateFormat DF = DateFormat.getDateInstance(DateFormat.SHORT);
System.out.printf("Generic Gregorian Calendar (after cutover)%n");
GregorianCalendar genericCal = new GregorianCalendar();
System.out.printf(" Changeover=%s%n", DF.format(genericCal.getGregorianChange()));
genericCal.set(1800, Calendar.JANUARY, 1);
System.out.printf("%3s %s%n", "", DF.format(genericCal.getTime()));
System.out.printf("Russian Gregorian Calendar (before cutover)%n");
GregorianCalendar russianCal = new GregorianCalendar();
russianCal.setGregorianChange(new GregorianCalendar(1918, Calendar.JANUARY, 31).getTime());
System.out.printf(" Changeover=%s%n", DF.format(russianCal.getGregorianChange()));
russianCal.set(1800, Calendar.JANUARY, 1);
System.out.printf("%3s %s%n", "", DF.format(russianCal.getTime()));
for (int i = 1; i < 15; i++) {
russianCal.add(Calendar.DAY_OF_YEAR, -1);
System.out.printf("%3d: %s %n", -i, DF.format(russianCal.getTime()));
}
}
这将输出:
Generic Gregorian Calendar (after cutover)
Changeover=1582/10/15
1800/01/01
Russian Gregorian Calendar (before cutover)
Changeover=1918/01/31
1800/01/12
-1: 1800/01/11
-2: 1800/01/10
-3: 1800/01/09
-4: 1800/01/08
-5: 1800/01/07
-6: 1800/01/06
-7: 1800/01/05
-8: 1800/01/04
-9: 1800/01/03
-10: 1800/01/02
-11: 1800/01/01
-12: 1799/12/31
-13: 1799/12/30
-14: 1799/12/29
11天的差异看起来与朱利安/格里高利转换时损失的天数相似,但这只适用于1918年1月31日之后的时期,在这种情况下(1918年1月31日之后是俄罗斯的2月14日,这是13天的差异)。
如果您能给我解释一下,或者帮我把日期定在我想要的时间,我将不胜感激。
不幸的是,我只能使用标准的java8库,目前还没有第三方库。而且,新的 java.time
类不会“自动”帮助实现julian/gregorian转换(如果我错了,我欢迎指针),所以我的计划b就是简单地进行计算,而不使用任何日期类。
1条答案
按热度按时间e5njpo681#
我同意你的代码是正确的,尽管有点混乱。为格式化您的俄罗斯日期,您需要指示您的格式化使用俄罗斯公历交叉日期。
把你的俄罗斯日历设置为1月1日1800工程。没有变化发生。
输出为:
日期应该是1月1日(
Calendar
令人困惑地使用0表示一月)。当你把时间带到
Date
,你得到一个正常的java.util.Date
没有俄国人也没有朱利安。这个Date
对象表示一天中的某个时间,即俄罗斯的1月1日和公历的1月12日,在您的默认时区中。当你进一步格式化这个Date
使用DateFormat
在默认设置下,is使用1582年的标准公历交叉日期,因此打印1月12日。要打印1月1日,如在俄罗斯日历中一样,您需要指示格式化程序使用俄罗斯公历交叉日期。你通过传递一个GregorianCalendar
使用期望的交叉日期:我的时区中的输出:
其他选择?
不幸的是,您是正确的:java.time,现代的java日期和时间api,不支持julian日历开箱即用。我读到你不能使用任何第三方库。可考虑的选项包括:
对于其他可能使用第三方库的读者:joda time和it
GJChronology
. 它实行公历/儒略历制度,这是世界上大多数国家使用的历法制度…
对于您自己:您可以开发自己的julian gregorian年表来与java.time一起使用。这需要努力,但我希望它能带来一个漂亮的结果。
链接
oracle教程:date time解释如何使用java.time。
joda time的文档
GJChronology