调用getTime会更改日历值

mzl*_*mzl 12 java calendar

我想在给定日期的同一周内获得星期日.在此期间我遇到了这个问题:

Calendar calendar = Calendar.getInstance(Locale.GERMANY);
calendar.set(2017, 11, 11);
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
System.out.println(calendar.getTime().toString());
Run Code Online (Sandbox Code Playgroud)

结果在"Sun Jan 07 11:18:42 CET 2018"

Calendar calendar2 = Calendar.getInstance(Locale.GERMANY);
calendar2.set(2017, 11, 11);
calendar2.getTime();
calendar2.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
System.out.println(calendar2.getTime().toString());
Run Code Online (Sandbox Code Playgroud)

给了我正确的日期"Sun Dec 17 11:18:42 CET 2017"

有人能解释为什么第一个例子就是这样吗?这是真的有意吗?

谢谢

Jon*_*eet 10

基本上,CalendarAPI很糟糕,应该避免.它的描述并不十分清楚,但我认为我看到了它的发展方向,而且它在这种情况下表现得像预期的那样.我的意思是它遵循API作者的意图,而不是您或任何人阅读您的代码的意图......

文档:

可以通过调用set方法来设置日历字段值.在需要计算其时间值(距Epoch的毫秒数)或日历字段的值之前,不会解释日历中设置的任何字段值.调用get,getTimeInMillis,getTime,add和roll涉及这样的计算.

然后:

从日历字段计算日期和时间时,可能没有足够的信息用于计算(例如只有年月和月份没有日期),或者可能存在不一致的信息(例如1996年7月15日星期二(格里高利) ) - 1996年7月15日实际上是星期一).日历将解析日历字段值,以便按以下方式确定日期和时间.

如果日历字段值中存在任何冲突,则日历会优先考虑最近设置的日历字段.以下是日历字段的默认组合.将使用由最近设置的单个字段确定的最新组合.

对于日期字段:

  • 年+月+ DAY_OF_MONTH
  • 年+月+周W_K_MONTH + DAY_OF_WEEK
  • 年+月+ DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK
  • 年+ DAY_OF_YEAR
  • 年+ DAY_OF_WEEK + WEEK_OF_YEAR

在第一个例子中,最后一个字段集是"星期几"的事实意味着它将使用YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK计算(我认为).年和月已设定为2017年12月,但是星期是当前的周,即2018年1月的第5周......所以,当您说要设置星期几时星期天,它在2017年12月的"第5周"找到了星期天.12月只有4个星期,所以它有效地向前推进......我想.这一切都很混乱,基本上你不应该考虑这一点.

在第二个示例中,调用getTime()"锁定"您指定的年/月/日,并计算其他字段.当您设置星期几时,然后在现有的计算字段中对其进行调整.

基本上,尽可能避免使用此API.使用java.time,这是一种更清洁的日期/时间API.

  • 哈哈,同意你的看法,`Calendar`太可怕了,我们应该使用`java.time`. (2认同)