I have written a class which is able to represent cutoff timings for systems (uptimes or downtimes).
The difficulty of the use case within the question is that the end time lies before the start time. That implies that the downtime starts at some day of the week, and ends the next day at a certain time.
So Monday until Friday, from 18:00 until 07:00, implies that the system is also down on Saturday, midnight until 7:00. If we want to handle this correctly, we need to take that into account.
Below the source code of the class. The constructor accepts a Set
with the days of the week at which the cutoff times start, and the start and end times.
public class Uptime {
private final Set<DayOfWeek> daysOfUptimeStart;
private final LocalTime startTime;
private final LocalTime endTime;
public Uptime(Set<DayOfWeek> daysOfUptimeStart, LocalTime startTime, LocalTime endTime) {
this.daysOfUptimeStart = Collections.unmodifiableSet(daysOfUptimeStart);
this.startTime = startTime;
this.endTime = endTime;
}
public boolean isUp(LocalDateTime dateTime) {
LocalTime time = dateTime.toLocalTime();
if (!this.startTime.isAfter(this.endTime)) {
return this.daysOfUptimeStart.contains(dateTime.getDayOfWeek()) && !time.isBefore(this.startTime) && !time.isAfter(this.endTime);
}
else {
if (time.isBefore(this.startTime) && time.isAfter(this.endTime)) {
return false;
}
else {
return this.daysOfUptimeStart.contains(dateTime.getDayOfWeek().minus(!time.isBefore(this.startTime) ? 0 : 1));
}
}
}
}
Test
In order to test this, I have generated some dates: all dates from 14 to 20 September 2020 (Monday to Sunday), combined with 4 AM, 8 AM, 1 PM, 5 PM, 7 PM and 11 PM.
The code prints the datetimes, along with whether the system is up or not. We expect that:
- on Monday, the system is down at 7 PM and 11 PM;
- on Tuesday until Friday, the system is down at 4 AM, 7 PM and 11 PM;
- on Saturday, the system is down at 4 AM.
// Static importing java.time.DayOfWeek.* here
Uptime uptime = new Uptime(Set.of(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY), LocalTime.of(18, 0), LocalTime.of(7, 0));
YearMonth ym = YearMonth.of(2020, Month.SEPTEMBER);
List<LocalDateTime> datetimes = IntStream.rangeClosed(14, 20) // September 2020, MONDAY till SUNDAY
.mapToObj(ym::atDay)
.flatMap(date -> IntStream.of(4, 8, 13, 17, 19, 23)
.mapToObj(hour -> LocalTime.of(hour, 0))
.map(date::atTime))
.collect(Collectors.toList());
datetimes.forEach(datetime -> System.out.printf("%s %-12s %s\n", datetime, "(" + datetime.getDayOfWeek() + "):", !uptime.isUp(datetime)));
The output matches the expectation.
Update
A revision to the original post slightly changed the requirement. However,
you don't have to modify abovementioned code, as it'll still work if you modify your input. In fact, you are recording up-times instead of down-times. So instead, register your up-time times: Monday to Friday, 7:00 to 18:00.
Set<DayOfWeek> daysOfWeek = Set.of(MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY);
LocalTime start = LocalTime.of(7, 0);
LocalTime end = LocalTime.of(18, 0);
Uptime uptime = new Uptime(daysOfWeek, start, end);
Now with uptime.isUp(LocalDateTime.now())
you can still check whether the system is up.