Calendar.UNDECIMBER是做什么用的?

9

Calendar类中有一个常量叫做UNDECIMBER,它描述了第13个月。

这个常量有什么有用的目的吗?在维基百科上写道,它是为了农历日历。但是没有实现这样的日历。

是否存在任何解决方案来表示第14个月(Duodecimber)?

我在网上没有找到太多信息,我想更多地了解这个话题。


5
我以前从没听说过这个。也许他们只是希望有人会实现一个有时包含13个月的日历,所以才把它包括进去。也许确实有人实现了,但是这个实现并没有被包含在标准JRE中。 - Ole V.V.
4
如果有人不知道“Undecimber”中的“i”是什么意思:在拉丁语中,10是decem,两个音节中都含有字母e,而11是undecim,含有字母i(直到12月之前的月份名称来自于当时的一年以三月作为第一个月)。例如,请参考http://blogs.transparent.com/latin/latin-numbers-1-100/。 - Ole V.V.
2个回答

7
如已提到,一些农历(和其他古老的)日历有13个月。一个例子是科普特日历
虽然没有实现带有13个月的日历来扩展java.util.Calendar,但在Java 8的新API中有一些。随着新的java.time API的引入,也创建了ThreeTen Extra项目,其中包含此类的实现
该类为org.threeten.extra.chrono.CopticChronology,它扩展了本地的java.time.chrono.Chronology。我只是做了一个示例代码来创建此日历中的日期并循环遍历其月份:
// Coptic calendar
CopticChronology cal = CopticChronology.INSTANCE;
// range for month of year (from 1 to 13)
System.out.println("month range: " + cal.range(ChronoField.MONTH_OF_YEAR)); // 1 - 13

// getting a date in Coptic calendar and loop through the months
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy");
// September 11th is equivalent to 01/01 in Coptic calendar
CopticDate d = cal.date(LocalDate.of(2017, 9, 11));
for (int i = 0; i < 14; i++) {
    System.out.println(fmt.format(d));
    d = d.plus(1, ChronoUnit.MONTHS);
}

输出结果为:

month range: 1 - 13
01/01/1734
01/02/1734
01/03/1734
01/04/1734
01/05/1734
01/06/1734
01/07/1734
01/08/1734
01/09/1734
01/10/1734
01/11/1734
01/12/1734
01/13/1734
01/01/1735

请注意,第13个月结束后年份会发生变化。

ThreeTen Extra 项目也有一个实现, 用于埃塞俄比亚日历, 它也有 13 个月。


作为一个拥有14个月份的日历示例,PaxChronology实现了Pax Calendar:这是一个提出的改革日历系统,但据我所知目前并未使用。
引用维基百科:
普通年分为13个月,每个月28天,其名称与公历相同,除了在11月和12月之间有一个名为哥伦布的月份。每周、每月和每年的第一天都是星期日。
在闰年中,在哥伦布月份之后插入一个称为Pax的一周月份。
根据javadoc
闰年发生在以下情况下:年份的最后两位可被6整除,为99或为00且该年份不可被400整除。

例子:

PaxChronology paxCal = PaxChronology.INSTANCE;
System.out.println("month range: " + paxCal.range(ChronoField.MONTH_OF_YEAR));

PaxDate pd = paxCal.date(1930, 1, 1);
for (int i = 0; i < 15; i++) {
    // fmt is the same DateTimeFormatter from previous example
    System.out.println(fmt.format(pd));
    // adjusting for first day of next month - using TemporalAdjuster because
    // adding 1 ChronoUnit.MONTHS throws an exception for 14th month (not sure why)
    pd = pd.plus(30, ChronoUnit.DAYS).with(TemporalAdjusters.firstDayOfMonth());
}

输出:

month range: 1 - 13/14
01/01/1930
01/02/1930
01/03/1930
01/04/1930
01/05/1930
01/06/1930
01/07/1930
01/08/1930
01/09/1930
01/10/1930
01/11/1930
01/12/1930
01/13/1930
01/14/1930
01/01/1931

你可以注意到在第14个月后年份会改变。 范围是1-13/14,因为年份可以有13或14个月,这取决于它是否是闰年。

1
我担心这个答案与所要求的“UNDECIMBER”常量本身并没有直接关系。您还应该更正自己的陈述,“没有扩展java.util.Calendar”的实现。有一些实现:GregorianCalendar、BuddhistCalendar和JapaneseImperialCalendar(好吧,这3个日历只有12个月)。顺便说一句:日本日历在1872年之前有时会有13个月(在我的库Time4J中实现)。 - Meno Hochschild
1
@MenoHochschild 嗯,它并不是直接谈论UNDECIMBER,但我的理解是OP也问到了实现13个月历法的问题。我也纠正了我的陈述,非常感谢! - user7605325
1
有趣的是,你提到的科普特历实现曾经是 JSR-310 的一部分(随 Threeten-project 发布),但显然 Oracle 不想要它(据我所知,只作为 TCK-kit 中的测试类)。因此,在 Threeten-Extra 版本中根本没有本地化支持,因为 Oracle 没有提供任何文本资源。 - Meno Hochschild
如果我使用模式“MMM”,那就解释了为什么我在第13个月得到一个空字符串。 - user7605325
2
确实,但这个间隔(没有i18n)对整个threeten-extra项目都是正确的。为了比较,请查看我的api-example [EthiopicCalendar](http://time4j.net/javadoc-en/net/time4j/calendar/EthiopianCalendar.html)使用阿姆哈拉语,由于`DateTimeFormatter`的某些设计限制,它将永远无法在threeten-extra中实现(请注意仅使用埃塞俄比亚数字作为年份部分)。 - Meno Hochschild

4

然而,它似乎是任意的或者不完整的。 - Norbert Koch
@NorbertKoch 欢迎来到编程的世界。:) ... 但我认为它可能会被使用,例如中国日历是农历。您可以在这两个之间进行转换,也许那时您需要这个常数(?):https://dev59.com/wYjca4cB1Zd3GeqPyIlq - hamena314
1
好的,这篇文章澄清了这个常量支持实现。对我来说,JavaDoc读起来像是:“我们有这个常量,但无论如何”。现在更容易理解了。 - Norbert Koch
@NorbertKoch 在标准的Java中,确实没有实现或使用UNDECIMBER。据我所知,ICU4J使用非常类似的常量来支持一些拥有13个月份的日历(如中国、希伯来、科普特和埃塞俄比亚),但ICU4J类是在另一个包中定义的。 - Meno Hochschild

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接