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

问题描述

由于getActualMinimum()getGreatestMinimum()将为每个字段返回相同的值,所以真正的区别是什么?

解决方法

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

getGreatestMinimum()方法返回getActualMinimum()可能具有的最大可能值。尽管在大多数情况下,这些值始终是相同的(月份几乎总是以1开头),但是在某些罕见情况下,代码允许它们有所不同。使用getGreatestMinimum()适用于数据验证方案。

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

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

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都是相同的。

With the modern date-time 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的更多信息。

,

没有诸如minimumminimum这样的方法。这些方法是getActualMaximum(),getActualMinimum(),getLeastMaximum(),getMaximum()和getMinimum()

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

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

因此,Actuals是相对的,而其他3种方法是绝对的。

我只是通读了Java文档和下面的2个链接,得出了这个结论

getActualMaximum()

getActualMinimum()