gregoriancalendar在切换之前设置意外的日期

mhd8tkvw  于 2021-07-08  发布在  Java
关注(0)|答案(1)|浏览(328)

热释光;医生:我在做手术时得到了一个奇怪的结果 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就是简单地进行计算,而不使用任何日期类。

e5njpo68

e5njpo681#

我同意你的代码是正确的,尽管有点混乱。为格式化您的俄罗斯日期,您需要指示您的格式化使用俄罗斯公历交叉日期。
把你的俄罗斯日历设置为1月1日1800工程。没有变化发生。

GregorianCalendar russianCal = new GregorianCalendar();
    russianCal.setGregorianChange(
            new GregorianCalendar(1918, Calendar.JANUARY, 31).getTime());
    russianCal.set(1800, Calendar.JANUARY, 1);

    System.out.println("Russian month (0-based):      "
            + russianCal.get(Calendar.MONTH));
    System.out.println("Russian day of month:         "
            + russianCal.get(Calendar.DATE));

输出为:

Russian month (0-based):      0
Russian day of month:         1

日期应该是1月1日( Calendar 令人困惑地使用0表示一月)。
当你把时间带到 Date ,你得到一个正常的 java.util.Date 没有俄国人也没有朱利安。这个 Date 对象表示一天中的某个时间,即俄罗斯的1月1日和公历的1月12日,在您的默认时区中。当你进一步格式化这个 Date 使用 DateFormat 在默认设置下,is使用1582年的标准公历交叉日期,因此打印1月12日。要打印1月1日,如在俄罗斯日历中一样,您需要指示格式化程序使用俄罗斯公历交叉日期。你通过传递一个 GregorianCalendar 使用期望的交叉日期:

Date dateCorrespondingToRussianCal = russianCal.getTime();
    System.out.println("Corresponding java.util.Date: "
            + dateCorrespondingToRussianCal);

    DateFormat russianDateFormatter
            = DateFormat.getDateInstance(DateFormat.SHORT);
    russianDateFormatter.setCalendar(russianCal);
    System.out.println("Formatted Russian date:       "
            + russianDateFormatter.format(dateCorrespondingToRussianCal));

我的时区中的输出:

Corresponding java.util.Date: Sun Jan 12 13:10:30 CET 1800
Formatted Russian date:       1/1/00

其他选择?

不幸的是,您是正确的:java.time,现代的java日期和时间api,不支持julian日历开箱即用。我读到你不能使用任何第三方库。可考虑的选项包括:
对于其他可能使用第三方库的读者:joda time和it GJChronology . 它
实行公历/儒略历制度,这是世界上大多数国家使用的历法制度…
对于您自己:您可以开发自己的julian gregorian年表来与java.time一起使用。这需要努力,但我希望它能带来一个漂亮的结果。

链接

oracle教程:date time解释如何使用java.time。
joda time的文档 GJChronology

相关问题