我有一个Calendar实例,它从12月的第一天开始。我试图将Calendar实例设置为一年的最后一个星期二。在设置一年中的最后一天和一周中的某天之间,Calendar实例将还原为原始时间:
Calendar cal = ....;
Log.d(TAG, String.format("Starting here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
cal.set(Calendar.DAY_OF_YEAR, cal.getActualMaximum(Calendar.DAY_OF_YEAR));
cal.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
Log.d(TAG, String.format("Ending here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
/* Other stuff */
请给我2017和2018年的输出:
2017年:
Starting here 2017-12-1
Ending here 2017-11-28
2018:
Starting here 2018-12-1
Ending here 2018-11-27
但是,如果我从Calendar实例检索数据,则可以正常工作:
Calendar cal = ....;
Log.d(TAG, String.format("Starting here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
cal.set(Calendar.DAY_OF_YEAR, cal.getActualMaximum(Calendar.DAY_OF_YEAR));
// Ask the Calendar instance for information
long dummyValue = cal.getTimeInMillis();
cal.set(Calendar.DAY_OF_WEEK, Calendar.TUESDAY);
Log.d(TAG, String.format("Ending here %d-%d-%d", cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH)));
/* Other stuff */
请给我2017和2018年的输出:
2017年:
Starting here 2017-12-1
Ending here 2018-1-2
2018:
Starting here 2018-12-1
Ending here 2019-1-1
是的,我知道第二组值的日期不是最后一个星期二。这就是/* Other stuff */
的目的。
答案 0 :(得分:1)
LocalDate myLocalDate = LocalDate.of(2017, Month.DECEMBER, 1);
System.out.format("Starting here: %s%n", myLocalDate);
LocalDate lastTuesdayOfYear = myLocalDate
.with(TemporalAdjusters.lastDayOfYear())
.with(TemporalAdjusters.previousOrSame(DayOfWeek.TUESDAY));
System.out.format("Ending here: %s%n", lastTuesdayOfYear);
2017年的产出:
Starting here: 2017-12-01 Ending here: 2017-12-26
对于2018年:
Starting here: 2018-12-01 Ending here: 2018-12-25
此是给您一年中的最后一个星期二。无需任何其他操作。
是的,java.time在较新和较旧的Android设备上均可正常运行。它只需要至少 Java 6 。
org.threeten.bp
导入日期和时间类。 Calendar
类只是令人困惑。在您的情况下,其行为取决于文档。请允许我引用:
日历字段分辨率
从日历字段计算日期和时间时,…可能存在不一致的信息 (例如1996年7月15日(星期二)(格里高利语)-1996年7月15日是 实际上是一个星期一)。
Calendar
会将日历字段值解析为 通过以下方式确定日期和时间。如果日历字段值存在任何冲突,则
Calendar
给出 最近设置的日历字段的优先级。的 以下是日历字段的默认组合。的 最新组合,由最近设置的单项确定 字段。对于日期字段:
YEAR + MONTH + DAY_OF_MONTH YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK YEAR + DAY_OF_YEAR YEAR + DAY_OF_WEEK + WEEK_OF_YEAR
...
对于您来说,DAY_OF_WEEK
是最近设置的。 DAY_OF_WEEK
在上述五个组合中的三个中。我不知道选哪个。它们都不包含您设置的另一个字段DAY_OF_YEAR
,因此没有使用DAY_OF_YEAR
。这说明了您看到的行为。如果您坚持使用Calendar
,则应该可以使用cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
到达某个地方,因为负值将从月底开始倒计时。
然而,Calendar
不仅设计不当且令人困惑,而且早已过时。因此,请考虑改用java.time。
java.time
。java.time
向Java 6和7(JSR-310的ThreeTen)的反向端口。