繁体   English   中英

Calendar 的 getActualMinimum 和 getGreatestMinimum 方法有什么区别?

[英]What's the difference between Calendar's getActualMinimum and getGreatestMinimum methods?

由于getActualMinimum()getGreatestMinimum()将为每个字段返回相同的值,那么究竟有什么区别呢?

getActualMinimum()方法返回属性可能具有的最小可能值。 例如, Calendar.DAY_OF_MONTH永远不会小于 1,因为没有月份以 0 或更少的日期开始。

getGreatestMinimum()方法返回getActualMinimum()可能拥有的最大可能值。 虽然在大多数情况下这些值总是相同的(月份几乎总是从 1 开始),但代码允许它们在极少数情况下不同。 使用getGreatestMinimum()适用于数据验证场景。

这可能(并且确实)发生的一个地方是日历中存在跳过日期或不连续性的情况。 例如,Java 的GregorianCalendar实现了转换日期之前的儒略历和该日期之后的格里高利历中的日期,因此有几天的间隔,日历中的日期根本不存在。

Calendar类的getGreatestMinimum()方法是抽象的,需要子类来实现。 JRE 对GregorianCalendar的实现表明,如果转换月份的“跳过天数”不包括该月的第一天,则DAY_OF_MONTH字段可能会有所不同:

public int getGreatestMinimum(int field) {
    if (field == DAY_OF_MONTH) {
        BaseCalendar.Date d = getGregorianCutoverDate();
        long mon1 = getFixedDateMonth1(d, gregorianCutoverDate);
        d = getCalendarDate(mon1);
        return Math.max(MIN_VALUES[field], d.getDayOfMonth());
    }
    return MIN_VALUES[field];
}

以此作为提示,您可以使用setGregorianChange()设置儒略到格里高利更改的转换日期。 默认情况下,它是 1582 年 10 月 15 日(从 1582 年 10 月 4 日起跳过了 10 天)。 不同的语言环境在不同的时间切换,例如英国在 1752 年 9 月 14 日(9 月 2 日之后的第二天)切换。

通过将此切换设置为一个月中的某个日期,使跳过的日期与该月的第一天重叠,我们可以生成这些边缘情况。

具有实际切换日期的实际基于语言环境的不连续性可能是罗马尼亚,其中 1919 年 3 月 31 日之后的第二天是 1919 年 4 月 14 日。因此,在罗马尼亚语言环境中,1919 年 4 月将仅包括从 14 到 30 的天数,并且getGreatestMin()将返回 14。

由于我没有安装该语言环境,我可以更改转换日期来模拟会发生什么:

GregorianCalendar cal = new GregorianCalendar();
// Deprecated, but an easy way of showing this example
cal.setGregorianChange(new Date(1911, Calendar.APRIL, 14));
System.out.println("actual min = " + cal.getActualMinimum(cal.DAY_OF_MONTH));
System.out.println("greatest min = " + cal.getGreatestMinimum(cal.DAY_OF_MONTH));

输出:

actual min = 1
greatest min = 14

如果您使用Date(Long.MIN_VALUE)作为转换,则存在另一个边缘情况,提供没有间隙的“纯公历”日历。 但在这种情况下,“时间的开始”是当月的 16 日(在公历中),所以在这种情况下最大的分钟是 16。

其他日历系统可能具有类似的不连续性和边缘情况。

我建议您停止使用过时且容易出错的java.util日期时间 API。 在现代日期时间 API 中, smallestMaximum是指最大值中的最小值,例如一个月的最大天数范围从28 (对于Feb )到31 ,因此smallestMaximum28

类似的情况与名称为自描述的largestMinimum的情况类似。 然而,不同于smallestMaximum其持有最大值范围内的最小值,我一直没能找到它的最大价值必须由举办最小值范围largestMinimum 换句话说,通过保持的值minimumlargestMinimum是相同的所有ChronoField秒。

使用现代日期时间 API

import java.time.temporal.ChronoField;

public class Main {
    public static void main(String[] args) {
        // e.g. Value range for ChronoField.DAY_OF_MONTH
        System.out.println("Stats of ChronoField.DAY_OF_MONTH:");
        System.out.println("Supported value range: " + ChronoField.DAY_OF_MONTH.range());
        System.out.println("Maximum supported value: " + ChronoField.DAY_OF_MONTH.range().getMaximum());
        System.out.println("Minimum supported value: " + ChronoField.DAY_OF_MONTH.range().getMinimum());
        System.out.println("Largest minimum supported value: " + ChronoField.DAY_OF_MONTH.range().getLargestMinimum());
        System.out
                .println("Smallest maximum supported value: " + ChronoField.DAY_OF_MONTH.range().getSmallestMaximum());

        // e.g. Value range for ChronoField.DAY_OF_YEAR
        System.out.println("\nStats of ChronoField.DAY_OF_YEAR:");
        System.out.println("Supported value range: " + ChronoField.DAY_OF_YEAR.range());
        System.out.println("Maximum supported value: " + ChronoField.DAY_OF_YEAR.range().getMaximum());
        System.out.println("Minimum supported value: " + ChronoField.DAY_OF_YEAR.range().getMinimum());
        System.out.println("Largest minimum supported value: " + ChronoField.DAY_OF_YEAR.range().getLargestMinimum());
        System.out.println("Smallest maximum supported value: " + ChronoField.DAY_OF_YEAR.range().getSmallestMaximum());
    }
}

输出:

Stats of ChronoField.DAY_OF_MONTH:
Supported value range: 1 - 28/31
Maximum supported value: 31
Minimum supported value: 1
Largest minimum supported value: 1
Smallest maximum supported value: 28

Stats of ChronoField.DAY_OF_YEAR:
Supported value range: 1 - 365/366
Maximum supported value: 366
Minimum supported value: 1
Largest minimum supported value: 1
Smallest maximum supported value: 365

检查TemporalAccessor#range以获取更多详细信息。 Trail: Date Time 中了解有关现代日期时间 API 的更多信息。

没有像 leastminimum 这样的方法。 方法是 getActualMaximum()、getActualMinimum()、getLeastMaximum()、getMaximum() 和 getMinimum()

getLeastMaximum() 将返回 28,getMaximum() 将返回 31,getMinimum() 将返回 1 作为输入作为 Calendar.DAY_OF_WEEK

带有“实际”的方法将返回特定于正在使用的日历实例值的相应最小值或最大值。 (有些日历一年有 13 个月)

所以实际值是相对的,其他 3 种方法是绝对的。

我只是通读了 java doc 和下面的 2 个链接来得出这个结论

getActualMaximum()

getActualMinimum()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM