繁体   English   中英

Java 日历 DAY_OF_WEEK 设置为零

[英]Java Calendar DAY_OF_WEEK SET to zero

我有这个来自 PROD(> 7 年)的非常旧的代码块要调试。 有一点我无法理解。 代码中的一部分会计算下一次任务将运行的时间,对于需要在星期天(星期一)专门运行的任务,它使用 Calendar.SUNDAY。 但是有一个陈述,即使在多次阅读文档后我也无法解释其行为

日历 cal = Calendar.getInstance(); cal.set(Calendar.DAY_OF_WEEK, 0);

因为天数从 1-7 ( Calendar.SUNDAYCalendar.SATURDAY )可以解释,但零在这里如何工作,为什么没有例外?

为什么没有例外?

这是因为您没有将宽松模式设置为false ,默认情况下为true

演示:

import java.util.Calendar;

public class Main {
    public static void main(String[] args) {
        Calendar cal = Calendar.getInstance();
        cal.setLenient(false);
        cal.set(Calendar.DAY_OF_WEEK, 0);
        System.out.println(cal.getTime());
    }
}

Output:

Exception in thread "main" java.lang.IllegalArgumentException: DAY_OF_WEEK

文档说:

任何超出范围的值要么在宽松模式下标准化,要么在非宽松模式下被检测为无效值

作为规范化的一部分,该值会翻转,例如以下代码将值设置为等效于cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY - 1)

cal.set(Calendar.DAY_OF_WEEK, 0);

同样,以下代码将值设置为相当于cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY - 2)

cal.set(Calendar.DAY_OF_WEEK, -1);

通过在“测试台”中尝试,我发现了这一点:

当数字 1-7 “溢出”时,它看起来是“日历集”调整值/整数。 我可以看到这种模式:

       Day Of Week:  1  2  3  4  5  6  7  | 1 2 3 4 5 6 7 | 1  2  3   4   5   6   7  | ... 
 Value of calendar: -6 -5 -4 -3 -2 -1  0  | 1 2 3 4 5 6 7 | 8  9  10  11  12  13  14 | ...

试验台:

public static void main(String[] args) {
    Calendar cal = Calendar.getInstance();
    cal.set(Calendar.DAY_OF_WEEK, -6);
    System.out.println("Calendar value -6 returns: " + cal.get(Calendar.DAY_OF_WEEK));

    cal.set(Calendar.DAY_OF_WEEK, 0);
    System.out.println("Calendar value 0 returns: " + cal.get(Calendar.DAY_OF_WEEK));

    cal.set(Calendar.DAY_OF_WEEK, 1);
    System.out.println("Calendar value 1 returns: " + cal.get(Calendar.DAY_OF_WEEK));

    cal.set(Calendar.DAY_OF_WEEK, 7);
    System.out.println("Calendar value 7 returns: " + cal.get(Calendar.DAY_OF_WEEK));

    cal.set(Calendar.DAY_OF_WEEK, 8);
    System.out.println("Calendar value 8 returns: " + cal.get(Calendar.DAY_OF_WEEK));

    cal.set(Calendar.DAY_OF_WEEK, 14);
    System.out.println("Calendar value 14 returns: " + cal.get(Calendar.DAY_OF_WEEK));
}

Output:

Calendar value -6 returns: 1
Calendar value 0 returns: 7
Calendar value 1 returns: 1
Calendar value 7 returns: 7
Calendar value 8 returns: 1
Calendar value 14 returns: 7

Output 是根据“模式”。

java.time

我建议您使用 java.time,现代 Java 日期和时间 API,用于您的日期和时间工作。 例如:

    LocalDate ld = LocalDate.now(ZoneId.systemDefault())
                            .with(DayOfWeek.TUESDAY);
    System.out.println(ld);

今天,6 月 5 日星期六,当我运行此代码时,output 是:

2021-06-01

是的,6 月 1 日是星期二。 由于我们将枚举常量传递给with() ,因此实际上不可能传递超出范围的值。 DayOfWeek是一个枚举,在一周的 7 天中包含 7 个值。 我们唯一能遇到的麻烦是通过null ,这将抛出NullPointerException ,我认为你想要。

但是,如果我们确实坚持将星期几作为数字传递,那是可能的。 java.time 编号从星期一 = 1 到星期日 = 7 的星期几。

    LocalDate ld = LocalDate.now(ZoneId.systemDefault())
                            .with(ChronoField.DAY_OF_WEEK, 2);

到目前为止,output 和以前一样是2021-06-01 但是如果我们通过 0 呢?

                            .with(ChronoField.DAY_OF_WEEK, 0);

线程“主”java.time.DateTimeException 中的异常:DayOfWeek 的值无效(有效值 1 - 7):0

我们不仅会收到您要求的例外情况,而且还会收到明确且有用的例外信息,恕我直言。

星期零在这里如何工作?

使用Calendar星期 0 的工作方式与 7 = 星期六相同。 似乎至少有一个宽松的老式GregorianCalendar在星期几执行一种模 7 运算,以将其置于 1 到 7 的区间内。我没有发现这个记录。 GregorianCalendar可能是您正在处理的Calendar的具体子类。 我尝试了不同的数字,它们都等于 7 模 7:

    int[] dows = { 0, 7, -7, 14, -14, -98 };
    for (int dow : dows) {
        Calendar cal = new GregorianCalendar(2021, Calendar.JUNE, 2);               
        Date dateBefore = cal.getTime();
        cal.set(Calendar.DAY_OF_WEEK, dow);
        System.out.format("%s and day of week %3d yields %s%n", dateBefore, dow, cal.getTime());
    }

Output:

 Wed Jun 02 00:00:00 CEST 2021 and day of week 0 yields Sat Jun 05 00:00:00 CEST 2021 Wed Jun 02 00:00:00 CEST 2021 and day of week 7 yields Sat Jun 05 00:00:00 CEST 2021 Wed Jun 02 00:00:00 CEST 2021 and day of week -7 yields Sat Jun 05 00:00:00 CEST 2021 Wed Jun 02 00:00:00 CEST 2021 and day of week 14 yields Sat Jun 05 00:00:00 CEST 2021 Wed Jun 02 00:00:00 CEST 2021 and day of week -14 yields Sat Jun 05 00:00:00 CEST 2021 Wed Jun 02 00:00:00 CEST 2021 and day of week -98 yields Sat Jun 05 00:00:00 CEST 2021

教程链接

Oracle 教程:日期时间解释如何使用 java.time。

暂无
暂无

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

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