1582 年 10 月 15 日之前日期的日历到日期转换.公历到儒略历切换
鉴于公历开始日期是 1582 年 10 月 15 日,请考虑以下测试并帮助我了解会发生什么:
Given that Gregorian Calendar start date is 15 Oct 1582, please consider the following tests and please help me understanding what happens:
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import org.junit.Test;
@Test
public void gregorianToDateConversion() {
GregorianCalendar calendar = null;
Date date = null;
calendar = new GregorianCalendar(1582, 9, 04);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 9, 4) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
calendar = new GregorianCalendar(1582, 9, 05);
date = calendar.getTime();
System.out.println("
new GregorianCalendar(1582, 9, 5) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
calendar = new GregorianCalendar(1582, 9, 14);
date = calendar.getTime();
System.out.println("
new GregorianCalendar(1582, 9, 14) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
calendar = new GregorianCalendar(1582, 9, 15);
date = calendar.getTime();
System.out.println("
new GregorianCalendar(1582, 9, 15) -> calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date:" + date);
String dateToParse = null;
dateToParse = "1582-10-04";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
dateToParse = "1582-10-05";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
dateToParse = "1582-10-14";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
dateToParse = "1582-10-15";
System.out.println("
String to parse: " + dateToParse);
calendar = parseDateTime(dateToParse);
if(calendar != null) {
date = calendar.getTime();
System.out.println("datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("calendar.getTime() -> Date: " + date);
}
}
private GregorianCalendar parseDateTime(String s) {
DatatypeFactory datatypeFactory = null;
try {
datatypeFactory = DatatypeFactory.newInstance();
return datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
结果如下:
new GregorianCalendar(1582, 9, 4) -> calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date:Thu Oct 04 00:00:00 CET 1582 **OK**
new GregorianCalendar(1582, 9, 5) -> calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]] **+ 10 days ??**
calendar.getTime() -> Date:Fri Oct 15 00:00:00 CET 1582 **coherent with calendar**
new GregorianCalendar(1582, 9, 14) -> calendar[DAY_OF_MONTH [24], MONTH [9], YEAR [1582]] **+ 10 days ??**
calendar.getTime() -> Date:Sun Oct 24 00:00:00 CET 1582 **coherent with calendar**
new GregorianCalendar(1582, 9, 15) -> calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date:Fri Oct 15 00:00:00 CET 1582 **OK**
String to parse: 1582-10-04
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]
calendar.getTime() -> Date: Mon Sep 24 00:00:00 CET 1582 **Not coherent with calendar. Conversion to julian date?**
String to parse: 1582-10-05
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]
calendar.getTime() -> Date: Tue Sep 25 00:00:00 CET 1582 **Not coherent with calendar. Conversion to julian date?**
String to parse: 1582-10-14
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [14], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date: Thu Oct 04 00:00:00 CET 1582 **Not coherent with calendar. Conversion to julian date?**
String to parse: 1582-10-15
datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar() ->
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]] **OK**
calendar.getTime() -> Date: Fri Oct 15 00:00:00 CET 1582 **OK**
你能解释一下发生了什么吗?非常感谢.
Could you clarify me what is happening? Thank you very much.
谢谢,我已经修正了我在解析日期格式方面的错误:现在都具有 yyyy-MM-gg 的形式,并且不再抛出异常.
Thank you, I've fixed my mistakes about the format of the date to parse: now all have the form yyyy-MM-gg and no exceptions are thrown anymore.
现在我试着澄清我的疑问.
Now I try to clarify my dubts.
是什么决定了我们是否使用公历?
通过总结:
java.util.GregorianCalendar 表示 1582 年 10 月 15 日之前日期的儒略历和该日期之后的公历.对吗?
因此,这证明了新 GregorianCalendar(...) 中的行为...
如果我这样做:
What determines whether or not we are using the proleptic gregorian calendar?
By summarizing:
java.util.GregorianCalendar represents a julian calendar for dates before 15 Oct 1582 and a gregorian calendar after this date. Is it right?
So, this justifies the behaviour in the new GregorianCalendar(...)...
If I do:
new GregorianCalendar(1582, 9, 4)
我有
calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]
因为 1582 年 10 月 4 日存在于儒略历中,而我创建的日历代表儒略日期.
将此日历转换为日期,我们有:
because 4 Oct 1582 exists in the julian calendar and the calendar I've created represents a julian date.
Converting this calendar to date, we have:
Date:Thu Oct 04 00:00:00 CET 1582, consistent with Calendar.
如果我这样做:
new GregorianCalendar(1582, 9, 5)
我得到
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]
因为 10 月 5 日在儒略历和公历中都不存在.因此 GregorianCalendar 构造函数在 10 月 4 日之后的 1 天创建了一个日期,即公历的第一天,即 10 月 15 日.然后用公历系统表示新日期.
创建一个从 (1582, 9, 5) 到 (1582, 9, 14) 的新日历传递日期时,我也会有同样的行为.
在上面的例子中,转换后的 java.util.Date 再次与 Calendar 一致
because the day 5 of October neither exists in julian nor in gregorian calendar. So the GregorianCalendar constructor creates a date exactely 1 day after the 4 of October, that is the first day of the gregorian calendar, the 15 of October. The new date is then expressed in gregorian calendar system.
I'll have the same behaviour creating a new calendar passing dates from (1582, 9, 5) to (1582, 9, 14).
In the example above, the converted java.util.Date is again consistent with the Calendar
Date:Fri Oct 15 00:00:00 CET 1582
如果我这样做:
new GregorianCalendar(1582, 9, 15)
我有
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]
因为 10 月 15 日存在于公历中,并且新日期在此系统中表示.转换为 Date 的 Calendar 再次保持一致:
because 15 of October exists in gregorian calendar and the new date is expressed in this system. The Calendar converted into Date is again consistent:
Date:Fri Oct 15 00:00:00 CET 1582
这意味着 GregorianCalendar 构造函数假定我在日历系统中输入了在给定纪元中有效的日期:换句话说,假定如果我输入的日期早于或等于 10 月 4 日,我认为日期是根据到儒略历并且日期在这个系统中表示,如果我输入一个介于 10 月 5 日到 14 日之间的日期,它会计算儒略历的结束日期(10 月 4 日)和我输入的日期之间的天数,并将这些天数相加为公历的开始日期(10 月 15 日)并以公历表示新日期,如果我输入的日期在 10 月 15 日之后或等于 10 月 15 日,则假定我输入的日期是公历,新日期表示为这个系统.
这一切都正确吗?
这不是一种预兆行为,对吧?如果日历是公历,我希望用
This means that the GregorianCalendar constructor assumes that I enter dates in the calendar system that is valid in the given epoch: in other words assumes that if I enter a date prior then or equal to 04 October I'm thinking the date according to the julian calendar and the date is expressed in this system, if I enter a date between 05 and 14 October it counts the number of days between the end date of julian calendar (04 october) and the date I entered and sums this days to the start date of gregorian calendar (15 October) and express the new date in gregorian system, and if I enter a date after or equal to 15 October it assumes that the date I entered is meant in gregorian calendar and the new date is expressed in this system.
Is all this correct?
This is not a proleptic behaviour, right? If the calendar was a proleptic gregorian calendar I would expect that initializing it with
new GregorianCalendar(1582, 9, 5)
我会得到
calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]
如果日期在公历系统中不存在,也设置为 10 月 5 日,并且在公历的第一天之前 10 天,如果我是,它将等于儒略日期 9 月 25 日没记错.
我如何决定是否使用公历?
that is the 5 of October is set also if the date does not exists in the gregorian system and, being 10 days befor the first day of gregorian calendar, it would be equal to the julian date 25 september, if I'm not mistaken.
How can I decide to use the proleptic gregorian calendar or not?
解析一个字符串并通过 XmlGregorianCalendar 创建一个新的 GregorianCalendar,在我看来,这种行为有所不同.
解析1582-10-04"我得到
Parsing a String and creating a new GregorianCalendar passing through the XmlGregorianCalendar, the behaviour seems to me different.
Parsing "1582-10-04" I obtain
calendar[DAY_OF_MONTH [4], MONTH [9], YEAR [1582]]
(和上面的例子一样)但是一个日期
(same as the example above..) but a date
Date: Mon Sep 24 00:00:00 CET 1582
(这里我们有一个儒略日期,对吗?但在上面的例子中(GregorianCalendar 是由它的构造函数创建的)Date 等于 Calendar.为什么现在它不同了?
(Here we have a julian date, is it right? But in the example above (where the GregorianCalendar was created by its constructor) the Date was equal to the Calendar. Why now it is different?
解析我们得到的字符串1582-10-05"
Parsing the string "1582-10-05" we have
calendar[DAY_OF_MONTH [5], MONTH [9], YEAR [1582]]
(现在我们有了 Proleptic 公历,对吗?)
但又是一个不同的日期
(Now we have a Proleptic gregorian calendar, right?)
But again a different Date
Date: Tue Sep 25 00:00:00 CET 1582 (Julian Date? Why?)
解析1582-10-14"的行为相同
Same behaviour parsing "1582-10-14"
calendar[DAY_OF_MONTH [14], MONTH [9], YEAR [1582]]
Date: Thu Oct 04 00:00:00 CET 1582
如果我们最终解析1582-10-15",我们回来的公历时代广告都变得一致:
If we finally parse "1582-10-15", we come back in the Gregorian age ad all become consistent:
calendar[DAY_OF_MONTH [15], MONTH [9], YEAR [1582]]
Date: Fri Oct 15 00:00:00 CET 1582
你能帮我理解所有这些行为吗?
非常感谢你.
Can you help me to understand all this behaviours?
Thank you very much.
编辑 2:
感谢您的回答,如果我仍有疑问.我尝试了以下代码:
Thank you for your answers, also if some doubt remains for me. I tried the following code:
GregorianCalendar proleptic = new GregorianCalendar();
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, 9);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
Date prolepticDate = proleptic.getTime();
System.out.println("prolepticDate ["+prolepticDate+"]");
输出是:
proleptic [DAY_OF_MONTH [5], MONTH [9], YEAR [1582]
prolepticDate [Tue Sep 25 00:24:07 CET 1582]
现在我的日历 DAY_OF_MONTH 与我设置的一致,所以我认为这是一种预兆行为,对吧?但是我再次问为什么 getTime() 方法获得的日期不代表同一天,而是 10 天前.再次感谢.
Now I have the calendar with DAY_OF_MONTH consistent with what I've set, so I think this is a proleptic behaviour, right? But again I ask why the Date, obtained by the getTime() method, does not represent the same day, but 10 days before. Thanks again.
编辑 3:
这个问题对我来说更清楚一些,但并不完全.我没有详细理解从 GregorianCalendar 到 Date 的转换是通过什么逻辑完成的,以及为什么一个预测的公历和一个传统的公历,每个都使用与 DAY、MONTH 和 YEAR 相同的参数构造,并不总是代表相同的时刻.我做了一些进一步的测试.
The question is for me a bit clearer, but not completely. I did not understand in detail by what logic the conversion from GregorianCalendar to Date is done and why a proleptic Gregorian Calendar and a traditional one, each constructed with the same parameters as DAY, MONTH and YEAR, not always represent the same instant of time. I did some further tests.
GregorianCalendar proleptic = null;
GregorianCalendar calendar = null;
Date date = null;
// ---- JULIAN PERIOD ----
proleptic = new GregorianCalendar();
proleptic.clear();
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, Calendar.FEBRUARY);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic_calendar_5Feb1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
date = proleptic.getTime();
System.out.println("date_5Feb1582 from proleptic ["+date+"]");
calendar = new GregorianCalendar(1582, 1, 5);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 1, 5) -> [DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("new GregorianCalendar(1582, 1, 5) .getTime() -> Date:" + date);
System.out.println("proleptic_calendar_5Feb1582 in millis ["+proleptic.getTimeInMillis()+"], new GregorianCalendar(1582, 1, 5) in millis ["+calendar.getTimeInMillis()+"], millis are equal ["+ (proleptic.getTimeInMillis() == calendar.getTimeInMillis()) +"]");
//--------
System.out.println("
");
// ---- transition period ----
proleptic = new GregorianCalendar();
proleptic.clear();
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 8);
proleptic.set(Calendar.MONTH, Calendar.OCTOBER);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic_calendar_8Oct1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
date = proleptic.getTime();
System.out.println("date_5Oct1582 from proleptic ["+date+"]");
calendar = new GregorianCalendar(1582, 9, 8);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 9, 8) -> [DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("new GregorianCalendar(1582, 9, 8) .getTime() -> Date:" + date);
System.out.println("proleptic_calendar_8Oct1582 in millis ["+proleptic.getTimeInMillis()+"], new GregorianCalendar(1582, 9, 8) in millis ["+calendar.getTimeInMillis()+"], millis are equal ["+ (proleptic.getTimeInMillis() == calendar.getTimeInMillis()) +"]");
//--------
System.out.println("
");
// ---- GREGORIAN PERIOD ----
proleptic = new GregorianCalendar();
proleptic.clear();
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, Calendar.DECEMBER);
proleptic.set(Calendar.YEAR, 1582);
System.out.println("proleptic_calendar_5Dec1582 [DAY_OF_MONTH ["+proleptic.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+proleptic.get(Calendar.MONTH)+"], YEAR ["+proleptic.get(Calendar.YEAR)+"]");
date = proleptic.getTime();
System.out.println("date_5Dec1582 from proleptic ["+date+"]");
calendar = new GregorianCalendar(1582, 11, 5);
date = calendar.getTime();
System.out.println("new GregorianCalendar(1582, 11, 5) -> [DAY_OF_MONTH ["+calendar.get(Calendar.DAY_OF_MONTH)+"], MONTH ["+calendar.get(Calendar.MONTH)+"], YEAR ["+calendar.get(Calendar.YEAR)+"]]");
System.out.println("new GregorianCalendar(1582, 11, 5) .getTime() -> Date:" + date);
System.out.println("proleptic_calendar_5Dec1582 in millis ["+proleptic.getTimeInMillis()+"], new GregorianCalendar(1582, 11, 5) in millis ["+calendar.getTimeInMillis()+"], millis are equal ["+ (proleptic.getTimeInMillis() == calendar.getTimeInMillis()) +"]");
//--------
输出是:
proleptic_calendar_5Feb1582 [DAY_OF_MONTH [5], MONTH [1], YEAR [1582]
date_5Feb1582 from proleptic [Fri Jan 26 00:00:00 CET 1582]
new GregorianCalendar(1582, 1, 5) -> [DAY_OF_MONTH [5], MONTH [1], YEAR [1582]]
new GregorianCalendar(1582, 1, 5) .getTime() -> Date:Mon Feb 05 00:00:00 CET 1582
proleptic_calendar_5Feb1582 in millis [-12241069200000], new GregorianCalendar(1582, 1, 5) in millis [-12240205200000], millis are equal [false]
proleptic_calendar_8Oct1582 [DAY_OF_MONTH [8], MONTH [9], YEAR [1582]
date_5Oct1582 from proleptic [Fri Sep 28 00:00:00 CET 1582]
new GregorianCalendar(1582, 9, 8) -> [DAY_OF_MONTH [18], MONTH [9], YEAR [1582]]
new GregorianCalendar(1582, 9, 8) .getTime() -> Date:Mon Oct 18 00:00:00 CET 1582
proleptic_calendar_8Oct1582 in millis [-12219901200000], new GregorianCalendar(1582, 9, 8) in millis [-12219037200000], millis are equal [false]
proleptic_calendar_5Dec1582 [DAY_OF_MONTH [5], MONTH [11], YEAR [1582]
date_5Dec1582 from proleptic [Sun Dec 05 00:00:00 CET 1582]
new GregorianCalendar(1582, 11, 5) -> [DAY_OF_MONTH [5], MONTH [11], YEAR [1582]]
new GregorianCalendar(1582, 11, 5) .getTime() -> Date:Sun Dec 05 00:00:00 CET 1582
proleptic_calendar_5Dec1582 in millis [-12214890000000], new GregorianCalendar(1582, 11, 5) in millis [-12214890000000], millis are equal [true]
第一个测试(1582 年 2 月 5 日)指的是属于儒略历的时期,第二个(1582 年 10 月 8 日)属于过渡时期,第三个(1582 年 12 月 5 日)属于公历时期.然后我觉得要注意以下几点:
The first test (5 Feb 1582) refers to a period belonging to the Julian calendar, the second (8 Oct 1582) belongs to the period of transition, the third (5 Dec 1582) to the Gregorian Calendar period. Then I think to notice the following things:
儒略时期
- 预测的公历似乎代表了期望的日期
- 如@Meno Hochschild 所述,获得的日期被转换为儒略日期(-10 天)
- 传统的公历似乎也代表了希望的日期...
- 但是获取到的Date和之前的不一样
- 其实,两个公历代表两个不同的时间瞬间,看毫秒值
过渡期
- 预测的公历似乎代表了期望的日期
- 再次将获得的日期转换为儒略日期(-10 天)
- 传统的公历似乎是公历转换的结果(10 月 8 日),最初以预测儒略历表示(10 月 8 日 = 4 天,然后儒略历 MAX DATE(10 月 4 日)= 3比公历多天 MIN DATE = 15 + 3 = 10 月 18 日(这是一个假设)
- 这次获取的Date好像代表了上面传统公历的同一个日期(这次没有转换为儒略日?)
- 两个公历再次代表两个不同的时刻,查看毫秒值
公历
- 预测的公历代表期望的日期
- 获取的Date代表相同的日期
- 传统的公历代表所需的日期
- 获取的Date代表相同的日期
- 两个公历代表同一时刻,同一毫秒数
你能帮我一一解释所有这些结果吗?
Could you help me to explain one by one all of these results?
谢谢.
推荐答案
方法 newXMLGregorianCalendar(s)
必须输入格式为yyyy-MM-dd"的字符串,即使用 两位数表示月份中的某天.但是您已经定义了字符串1582-10-4"和1582-10-5"(而不是1582-10-04"和1582-10-05").
Method newXMLGregorianCalendar(s)
must be feeded with a string in format "yyyy-MM-dd", that is using TWO digits for the day of month. But you have defined the strings "1582-10-4" and "1582-10-5" (instead of "1582-10-04" and "1582-10-05").
我已经测试了替代品,它可以工作.
I have tested the replacement, and it works.
请记住,XMLGregorianCalendar 非常严格,并且还根据 ISO-8601 中的标准约定使用预测公历.这意味着,它甚至在 1582 年之前就使用公历闰年规则.这解释了您的陈述与日历不一致.转换为儒略日期?".例如:
Remember that XMLGregorianCalendar is very strict and also uses the proleptic gregorian calendar according to the standard convention in ISO-8601. That means, it uses the gregorian leap year rules even before 1582. This explains your statement "Not coherent with calendar. Conversion to julian date?". For example:
教皇在日期 1582-10-04(旧儒略历)之后的 10 天撤职,因此在此之后,日期 1582-10-15 在新公历中紧随其后.在公历中,日期 1582-10-14 定义明确,对应于 1582-10-15 的前一天,因此(历史儒略)日期为 1582-10-04.
The pope had removed 10 days following the date 1582-10-04 (in old julian calendar), so after this the date 1582-10-15 immediately followed in new gregorian calendar. In the proleptic gregorian calendar the date 1582-10-14 is well defined and corresponds to one day before 1582-10-15, hence the (historic julian) date 1582-10-04.
OP 编辑后更新:
您的问题是什么决定了我们是否使用公历?"的简单答案是:你决定.
The simple answer to your question "What determines whether or not we are using the proleptic gregorian calendar?" is: You decide.
详细说明:如果您使用 XMLGregorianCalendar
,那么您使用的是公历.
In detail: If you use XMLGregorianCalendar
then you use the proleptic gregorian calendar.
如果你使用 java.util.GregorianCalendar
那么你默认选择了日期 1582-10-15 作为公历的第一天.所有过去的日子都被认为是在儒略历中.但是,您可以覆盖默认切换日期.为此,您只需调用方法 setGregorianChange(Date) 带有适当的参数.new Date(Long.MIN_VALUE)
的参数设置预测公历,而 new Date(Long.MAX_VALUE)
的参数设置预测儒略历.
If you use java.util.GregorianCalendar
then you have choosen the date 1582-10-15 as the first day of gregorian calendar by default. All former days are considered as being in julian calendar. You can override the default switch date however. For this to make work you just call the method setGregorianChange(Date) with an appropriate argument. An argument of new Date(Long.MIN_VALUE)
sets the proleptic gregorian calendar while an argument of new Date(Long.MAX_VALUE)
sets the proleptic julian calendar.
同样重要的是要注意
a) 大多数国家在 1582 年 10 月 15 日没有改用公历(只有主要的天主教国家),
a) most countries did not switch to gregorian calendar in 1582-10-15 (only major catholic countries),
b) 历史日期由其他因素进一步确定,例如不同的年初(这使得 JDK 中的整个 julian-gregorian-calendar-implementation 完全不足 - 目前没有提供支持的库).
b) historical dates are further determined by other factors like different start of year (which makes the whole julian-gregorian-calendar-implementation in JDK completely insufficient - currently there is no library which gives support).
EDIT-2 后更新:
输出 proleptic [DAY_OF_MONTH [5], MONTH [9], YEAR [1582]
符合预期,并保留了 proleptic 公历中定义的输入(1582-10-15 前 10 天)向后应用公历闰年规则).
The output proleptic [DAY_OF_MONTH [5], MONTH [9], YEAR [1582]
is as expected and conserves the input as defined in proleptic gregorian calendar (10 days before 1582-10-15 applying the gregorian leap year rules backwards).
输出 prolepticDate [Tue Sep 25 00:24:07 CET 1582]
是一个完全不同的故事.但是如果您记得您确实在 java.util.Date
上调用了方法 toString()
,那就可以理解了.此方法在内部实例化一个新的公历对象,默认开关为 1582-10-15. Date
-对象不知道(也没有内部状态)设置公历更改的日期,因此它的 toString()
方法只应用默认值.最后,预测日历对象只是重新计算/重新格式化为 Date.toString()
特定格式的儒略历表示.即:1582-09-25(切换前十天).
The output prolepticDate [Tue Sep 25 00:24:07 CET 1582]
is a completely different story. But it is understandable if you remember that you really called the method toString()
on java.util.Date
. This method internally instantiates a new gregorian calendar object with the default switch of 1582-10-15. A Date
-object has no idea (and no internal state) about setting the date for gregorian change, so its toString()
-method just applies the default. Finally the proleptic calendar object is just recalculated/reformatted to a julian calendar representation in the specific format of Date.toString()
. That is: 1582-09-25 (ten days before the switch).
由于@VGR 的评论而更新:
我的测试验证,例如对于预测日期 1582-10-05,XMLGregorianCalendar
和新 GregorianCalendar
的专门构造自 unix 以来以毫秒为单位产生相同的时间-epoch,见这里:
My test verifies that for example for the proleptic date 1582-10-05 both XMLGregorianCalendar
and a specialized construction of a new GregorianCalendar
yield the same time in millis since unix-epoch, see here:
String s = "1582-10-05";
DatatypeFactory datatypeFactory = DatatypeFactory.newInstance();
GregorianCalendar xml = datatypeFactory.newXMLGregorianCalendar(s).toGregorianCalendar();
GregorianCalendar proleptic = new GregorianCalendar();
proleptic.clear(); // very important for proper comparison to reset time part to zero
proleptic.setGregorianChange(new Date(Long.MIN_VALUE));
proleptic.set(Calendar.DAY_OF_MONTH, 5);
proleptic.set(Calendar.MONTH, Calendar.OCTOBER);
proleptic.set(Calendar.YEAR, 1582);
boolean isEqual = (xml.getTimeInMillis() == proleptic.getTimeInMillis());
System.out.println("XML-millisSinceEpoch: " + xml.getTimeInMillis());
System.out.println("Proleptic-millisSinceEpoch: " + proleptic.getTimeInMillis());
System.out.println("XML==Proleptic (1582-10-05): " + isEqual);
System.out.println(
"proleptic [DAY_OF_MONTH [" + proleptic.get(Calendar.DAY_OF_MONTH) + "], MONTH ["
+ proleptic.get(Calendar.MONTH) + "], YEAR [" + proleptic.get(Calendar.YEAR) + "]"
);
System.out.println("Date.toString() [" + proleptic.getTime() + "]");
输出:
XML-millisSinceEpoch: -12220160400000
Proleptic-millisSinceEpoch: -12220160400000
XML==Proleptic (1582-10-05): true
proleptic [DAY_OF_MONTH [5], MONTH [9], YEAR [1582]
Date.toString() [Tue Sep 25 00:00:00 CET 1582]
相关文章