1

I have a scenario where a system remains down each day from 18:00 to next day 07:00 for all working days (in short, "Mon - Fri, 18:00 to 07:00"). That means, each week day system is going down at 18:00 and getting up at 07:00 next day morning. Outside this time range, system is down e.g. from Friday 18:00 till Monday 07:00. I need to store this time and match in my java application against current time to see if the above system is up or not.

Can you please suggest how should I proceed storing the system down timing (may be in a variable) and match against current time in my application to find out if system is down at current time or not? I need to do this using Java.

I tried multiple Java documentation for date and time, but couldn't get anything useful in this situation.

Sonu
  • 65
  • 3
  • 10
  • 2
    Looks like a scenario made for the use of `java.time`... What have you tried so far? Can you show us some code or ideas, at least? – deHaar Sep 17 '20 at 12:27
  • You may be interested in this answer covering java.date/java.time API: https://stackoverflow.com/a/35300229/2519307 – MKorsch Sep 17 '20 at 12:29
  • I have major blocker to store the range of system down time. If I would have given a single stop and start datetime, I could find if the current time is within that. – Sonu Sep 17 '20 at 12:46
  • 1
    Monday to Friday, 18:00 until 07:00? Note that the last seven downtime hours of the week are actually on saturday. – MC Emperor Sep 17 '20 at 12:59
  • @MCEmperor: That's correct. Thanks for thinking ahead and letting me to avoid accidentally including this. – Sonu Sep 17 '20 at 13:08

2 Answers2

3

You can do something like:

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;

public class Main {
    public static void main(String[] args) {
        // Tests
        showServerStatus(List.of(DayOfWeek.SATURDAY, DayOfWeek.SUNDAY), LocalTime.of(7, 0), LocalTime.of(18, 0));
        showServerStatus(List.of(DayOfWeek.THURSDAY, DayOfWeek.SATURDAY), LocalTime.of(6, 0), LocalTime.of(20, 0));
    }

    static void showServerStatus(List<DayOfWeek> offDays, LocalTime startTime, LocalTime endTime) {
        LocalDateTime now = LocalDateTime.now();
        if (!offDays.contains(now.getDayOfWeek()) && !now.toLocalTime().isBefore(startTime)
                && !now.toLocalTime().isAfter(endTime)) {
            System.out.println("The server should be up now.");
        } else {
            System.out.println("The server should be down now.");
        }
    }
}

Output for me now:

The server should be up now.
The server should be down now.

Learn more about the modern date-time API from Trail: Date Time.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • Thanks for your putting efforts and writing this piece of code. That's helpful. But let's say, going forward, I get multiple such systems which have their own cutoff timings, I should not add conditions for all those. I am looking for a generic solution where lets say, "system A is down for Mon-Sat, 20:00 to 06:00, will I be able to proceed and send request to this". I would like to know how can I make aware my java program about this range in generic way. – Sonu Sep 17 '20 at 13:11
  • 1
    @Sonu - I've updated the answer to make it generic. – Arvind Kumar Avinash Sep 17 '20 at 13:46
2

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.

MC Emperor
  • 22,334
  • 15
  • 80
  • 130
  • Thanks for putting so much of efforts in writing down this code. This is very helpful. I appreciate that. This is working perfectly for week days scenarios, but during weekend, when system is down, it shows system is up...which I will modify the code and get this working as per my needs. Thanks again. – Sonu Sep 18 '20 at 09:25
  • @Sonu That is because in your question (revision 1) you describe that downtimes only occur from Monday until Friday — which means that on Saturdays and Sundays, the system would not be down. However, **the code need not to be changed**, just modify your input. I have updated the answer. – MC Emperor Sep 18 '20 at 09:41
  • Thanks @MC Emperor. Yes, that's why edited the question to explicitly mention it. But thanks a lot, your code is awesome. It gave me a lot of understanding in dealing with such scenarios. Thanks again. – Sonu Sep 18 '20 at 12:47