说我希望我的星期在星期二开始,那天应该从早上5:30开始。
这意味着,像这样的代码应该有效:
// LocalDateTimes created with the "standard" ISO time
LocalDateTime tuesday_4_30 = LocalDateTime.now()
.with(TemporalAdjusters.next(DayOfWeek.TUESDAY))
.withHour(4).withMinute(30);
LocalDateTime tuesday_6_30 = tuesday_4_30.withHour(6).withMinute(30);
LocalDateTime previous_monday = tuesday_4_30.minusDays(1);
// eventual adjustment using TemporalAdjusters here? like this?
// tuesday_4_30 = tuesday_4_30.with(new MyTemporalAdjuster(DayOfWeek.TUESDAY, 5, 30));
// <do the same for 6_30 and previous monday>
// or possibly change some global parameter like Chronology, Locale, or such..
Assert.assertEquals(tuesday_4_30.getDayOfWeek(), DayOfWeek.MONDAY);
Assert.assertEquals(tuesday_6_30.getDayOfWeek(), DayOfWeek.TUESDAY);
// there is 1 week between the previous monday and the next tuesday 6:30
Assert.assertEquals( ChronoUnit.WEEKS.between(previous_monday,tuesday_6_30), 1);
// there is 0 week between the previous monday and the next tuesday 4:30
Assert.assertEquals( ChronoUnit.WEEKS.between(previous_monday,tuesday_4_30), 0);
// 1 day between tuesday_4_30 and tuesday_6_30
Assert.assertEquals( ChronoUnit.DAYS.between(tuesday_4_30,tuesday_6_30), 1);
// 0 day between previous_monday and tuesday_4_30
Assert.assertEquals( ChronoUnit.DAYS.between(previous_monday,tuesday_4_30), 1);
我很想在这里使用时间调整器,我很确定我可以抵消时间和分钟,以便当天从5:30开始,但我无法弄清楚如何修改本周开始。
请注意,我查看了WeekFields,但我无法使其与ChronoUnit.XXX.between()
一起使用,所以我没有走得太远。看起来我不得不编写自己的年表,这似乎太过拉伸了。
你能帮助我吗?
答案 0 :(得分:3)
注意:ChronoUnit.WEEKS.between
计算两个日期之间的整周数(7天)。在你的情况下,星期一和星期二之间只有一天,所以它将返回0.你可能想要比较一年中的星期字段。
除非您想编写自己的年表(这会很痛苦),否则您可以通过以下方式“伪造”您的日历:
请参阅下面一个基于您的代码的粗略示例,它使所有测试都通过 - 您可能希望将逻辑提取到一个单独的类等。这有点hacky但可能足以满足您的用例。
@Test
public void test() {
LocalDateTime tuesday_4_30 = LocalDateTime.now()
.with(TemporalAdjusters.next(DayOfWeek.TUESDAY))
.withHour(4).withMinute(30);
LocalDateTime tuesday_6_30 = tuesday_4_30.withHour(6).withMinute(30);
LocalDateTime previous_monday = tuesday_4_30.minusDays(1);
// eventual adjustment using TemporalAdjusters here? like this?
// tuesday_4_30 = tuesday_4_30.with(new MyTemporalAdjuster(DayOfWeek.TUESDAY, 5, 30));
// <do the same for 6_30 and previous monday>
// or possibly change some global parameter like Chronology, Locale, or such..
assertEquals(dayOfWeek(tuesday_4_30), DayOfWeek.MONDAY);
assertEquals(dayOfWeek(tuesday_6_30), DayOfWeek.TUESDAY);
// there is 1 week between the previous monday and the next tuesday 6:30
assertEquals(weekBetween(previous_monday, tuesday_6_30), 1);
// there is 0 week between the previous monday and the next tuesday 4:30
assertEquals(weekBetween(previous_monday, tuesday_4_30), 0);
// 1 day between tuesday_4_30 and tuesday_6_30
assertEquals(weekBetween(tuesday_4_30, tuesday_6_30), 1);
// 0 day between previous_monday and tuesday_4_30
assertEquals(weekBetween(previous_monday, tuesday_4_30), 0);
}
private static DayOfWeek dayOfWeek(LocalDateTime date) {
return date.atOffset(ZoneOffset.ofHoursMinutes(5, 30)).withOffsetSameInstant(UTC).getDayOfWeek();
}
private static int weekBetween(LocalDateTime date1, LocalDateTime date2) {
OffsetDateTime date1UTC = date1.atOffset(ZoneOffset.ofHoursMinutes(5, 30)).withOffsetSameInstant(UTC);
OffsetDateTime date2UTC = date2.atOffset(ZoneOffset.ofHoursMinutes(5, 30)).withOffsetSameInstant(UTC);
int w1 = date1UTC.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
if (dayOfWeek(date1).getValue() >= TUESDAY.getValue()) w1++;
int w2 = date2UTC.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
if (dayOfWeek(date2).getValue() >= TUESDAY.getValue()) w2++;
return w2 - w1;
}
替代实施,也许更清洁:
private static DayOfWeek dayOfWeek(LocalDateTime date) {
return adjust(date).getDayOfWeek();
}
private static int weekBetween(LocalDateTime date1, LocalDateTime date2) {
int w1 = adjust(date1).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
if (dayOfWeek(date1).getValue() >= TUESDAY.getValue()) w1++;
int w2 = adjust(date2).get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
if (dayOfWeek(date2).getValue() >= TUESDAY.getValue()) w2++;
return w2 - w1;
}
private static LocalDateTime adjust(LocalDateTime date) {
return date.minusHours(5).minusMinutes(30);
}