Say I want my week to start on Tuesday, and the day should start at 5:30 am.
This means, code like this should work:
// 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);
I am tempted to use temporal adjusters here, and I'm quite sure I could offset the hours and minute so that the day starts at 5:30, but I can't figure out how to modify the start of the week.
Note that I looked into WeekFields but I can't make it work with ChronoUnit.XXX.between()
, so I didn't go too far. It looks like I would have to code my own Chronology, which seemed too far strectched.
Can you help me?
Note: ChronoUnit.WEEKS.between
counts the number of entire weeks (a period of 7 days) between two dates. In your case, there is only one days between the Monday and the Tuesday so it will return 0. You probably meant to compare the week of year fields instead.
Unless you want to write your own chronology (that's going to be a pain), you could "fake" your calendar by:
See below a rough example based on your code, that makes all the tests pass - you may want to extract the logic into a separate class etc. This is a bit hacky but may be enough for your use case.
@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;
}
Alternative implementation, maybe cleaner:
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);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With