import java.time.Duration;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Objects;
class Main {
public static void main
(String[] args
) { var startDate = LocalDate.of(2021, 10, 7);
var endDate = LocalDate.of(2021, 10, 14); // Exactly a week
var zone = ZoneId.of("Europe/Amsterdam");
var result = startDate.datesUntil(endDate)
.map(date -> nonWeekendHours(date, zone))
.reduce(Duration.ZERO, Duration::plus);
}
private static Duration nonWeekendHours(LocalDate date, ZoneId zone) {
LocalTimeRange result;
switch (date.getDayOfWeek()) {
case MONDAY:
case TUESDAY:
case WEDNESDAY:
case THURSDAY:
result = new LocalTimeRange(LocalTime.MIN, null);
break;
case FRIDAY:
result = new LocalTimeRange(null, LocalTime.NOON);
break;
case SATURDAY:
case SUNDAY:
result = new LocalTimeRange(null, null);
break;
default:
};
return result.toDuration(date, zone);
}
}
class LocalTimeRange {
public static final LocalTimeRange EMPTY = new LocalTimeRange(null, null);
private final LocalTime start;
private final LocalTime endExclusive;
public LocalTimeRange(LocalTime start, LocalTime endExclusive) {
this.start = start;
this.endExclusive = endExclusive;
}
public Duration toDuration(LocalDate date, ZoneId zone) {
if (start == null && endExclusive == null) {
return Duration.ZERO;
}
var s = ZonedDateTime.of(date, Objects.requireNonNullElse(start, LocalTime.MIN), zone);
ZonedDateTime e;
if (endExclusive != null) {
e = ZonedDateTime.of(date, endExclusive, zone);
}
else {
e = ZonedDateTime.of(date.plusDays(1), LocalTime.MIN, zone);
}
return Duration.between(s, e);
}
}
aW1wb3J0IGphdmEudGltZS5EdXJhdGlvbjsKaW1wb3J0IGphdmEudGltZS5Mb2NhbERhdGU7CmltcG9ydCBqYXZhLnRpbWUuTG9jYWxUaW1lOwppbXBvcnQgamF2YS50aW1lLlpvbmVJZDsKaW1wb3J0IGphdmEudGltZS5ab25lZERhdGVUaW1lOwppbXBvcnQgamF2YS51dGlsLk9iamVjdHM7CgpjbGFzcyBNYWluIHsKCglwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CgkJdmFyIHN0YXJ0RGF0ZSA9IExvY2FsRGF0ZS5vZigyMDIxLCAxMCwgNyk7CgkJdmFyIGVuZERhdGUgPSBMb2NhbERhdGUub2YoMjAyMSwgMTAsIDE0KTsgLy8gRXhhY3RseSBhIHdlZWsKCQl2YXIgem9uZSA9IFpvbmVJZC5vZigiRXVyb3BlL0Ftc3RlcmRhbSIpOwoKCQl2YXIgcmVzdWx0ID0gc3RhcnREYXRlLmRhdGVzVW50aWwoZW5kRGF0ZSkKCQkJLm1hcChkYXRlIC0+IG5vbldlZWtlbmRIb3VycyhkYXRlLCB6b25lKSkKCQkJLnJlZHVjZShEdXJhdGlvbi5aRVJPLCBEdXJhdGlvbjo6cGx1cyk7CgkJU3lzdGVtLm91dC5wcmludGxuKHJlc3VsdCk7Cgl9CgoJcHJpdmF0ZSBzdGF0aWMgRHVyYXRpb24gbm9uV2Vla2VuZEhvdXJzKExvY2FsRGF0ZSBkYXRlLCBab25lSWQgem9uZSkgewoJCUxvY2FsVGltZVJhbmdlIHJlc3VsdDsKCQlzd2l0Y2ggKGRhdGUuZ2V0RGF5T2ZXZWVrKCkpIHsKCQkJY2FzZSBNT05EQVk6CgkJCWNhc2UgVFVFU0RBWToKCQkJY2FzZSBXRURORVNEQVk6CgkJCWNhc2UgVEhVUlNEQVk6CgkJCQlyZXN1bHQgPSBuZXcgTG9jYWxUaW1lUmFuZ2UoTG9jYWxUaW1lLk1JTiwgbnVsbCk7CgkJCQlicmVhazsKCQkJY2FzZSBGUklEQVk6CgkJCQlyZXN1bHQgPSBuZXcgTG9jYWxUaW1lUmFuZ2UobnVsbCwgTG9jYWxUaW1lLk5PT04pOwoJCQkJYnJlYWs7CgkJCWNhc2UgU0FUVVJEQVk6CgkJCWNhc2UgU1VOREFZOgoJCQkJcmVzdWx0ID0gbmV3IExvY2FsVGltZVJhbmdlKG51bGwsIG51bGwpOwoJCQkJYnJlYWs7CgkJCWRlZmF1bHQ6CgkJCQl0aHJvdyBuZXcgSWxsZWdhbEFyZ3VtZW50RXhjZXB0aW9uKCJUaGlzIGNhbm5vdCBoYXBwZW4sIGFjdHVhbGx5Iik7CgkJfTsKCQlyZXR1cm4gcmVzdWx0LnRvRHVyYXRpb24oZGF0ZSwgem9uZSk7Cgl9Cn0KCmNsYXNzIExvY2FsVGltZVJhbmdlIHsKCglwdWJsaWMgc3RhdGljIGZpbmFsIExvY2FsVGltZVJhbmdlIEVNUFRZID0gbmV3IExvY2FsVGltZVJhbmdlKG51bGwsIG51bGwpOwoKCXByaXZhdGUgZmluYWwgTG9jYWxUaW1lIHN0YXJ0OwoJcHJpdmF0ZSBmaW5hbCBMb2NhbFRpbWUgZW5kRXhjbHVzaXZlOwoKCXB1YmxpYyBMb2NhbFRpbWVSYW5nZShMb2NhbFRpbWUgc3RhcnQsIExvY2FsVGltZSBlbmRFeGNsdXNpdmUpIHsKCQl0aGlzLnN0YXJ0ID0gc3RhcnQ7CgkJdGhpcy5lbmRFeGNsdXNpdmUgPSBlbmRFeGNsdXNpdmU7Cgl9CgoJcHVibGljIER1cmF0aW9uIHRvRHVyYXRpb24oTG9jYWxEYXRlIGRhdGUsIFpvbmVJZCB6b25lKSB7CgkJaWYgKHN0YXJ0ID09IG51bGwgJiYgZW5kRXhjbHVzaXZlID09IG51bGwpIHsKCQkJcmV0dXJuIER1cmF0aW9uLlpFUk87CgkJfQoKCQl2YXIgcyA9IFpvbmVkRGF0ZVRpbWUub2YoZGF0ZSwgT2JqZWN0cy5yZXF1aXJlTm9uTnVsbEVsc2Uoc3RhcnQsIExvY2FsVGltZS5NSU4pLCB6b25lKTsKCQlab25lZERhdGVUaW1lIGU7CgkJaWYgKGVuZEV4Y2x1c2l2ZSAhPSBudWxsKSB7CgkJCWUgPSBab25lZERhdGVUaW1lLm9mKGRhdGUsIGVuZEV4Y2x1c2l2ZSwgem9uZSk7CgkJfQoJCWVsc2UgewoJCQllID0gWm9uZWREYXRlVGltZS5vZihkYXRlLnBsdXNEYXlzKDEpLCBMb2NhbFRpbWUuTUlOLCB6b25lKTsKCQl9CgkJcmV0dXJuIER1cmF0aW9uLmJldHdlZW4ocywgZSk7Cgl9Cn0K