[英]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.SUNDAY
到Calendar.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 日期和时间 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.