2

I am dealing with the following problem. In my use case the user sets 2 dates upon first launch of the app, namely StartSleepingHours and StopSleepingHours.

For example, they could look like StartSleepingHours:Thu 2 Mar 20:00 2017 and StopSleepingHours:Thu 2 Mar 8:00 2017 (notice they are at the same date since this is the date they are set by the user). Now, my problem is that I have a periodic task that runs every 15 minutes to check if Now is between the interval StartSH and StopSH in order to determine whether or not to start an activity monitoring Service.

Obviously, I don't want my service to monitor the user's activity while sleeping. Currently, I am trying to extract only the Hour and Minute information from the StartSH and StopSH and create date objects from those in order to compare them with now but I am very confused and frustrated about how to check if now is within the interval Start/Stop SH in the future.

Currently I my code like that:

public static boolean isWithinSH(Date startSH, Date now, Date stopSH) {
    boolean isSH = false;

    Calendar calendar = Calendar.getInstance(Locale.UK);
    calendar.set(Calendar.HOUR_OF_DAY, startSH.getHours());
    calendar.set(Calendar.MINUTE, startSH.getMinutes());

    Date sameDayStartSH = calendar.getTime();

    calendar.set(Calendar.HOUR_OF_DAY, 23);
    calendar.set(Calendar.MINUTE, 59);
    Date midnight = calendar.getTime();

    calendar.add(Calendar.DAY_OF_WEEK, 1);
    calendar.set(Calendar.HOUR_OF_DAY, stopSH.getHours());
    calendar.set(Calendar.MINUTE, stopSH.getMinutes());

    Date currentStopSH = calendar.getTime();


    if (now.before(midnight) && now.after(sameDayStartSH)) {
        System.out.println("SLEEPING HOURS");
        isSH = true;
    } else if (now.after(midnight) && now.before(currentStopSH)) {
        System.out.println("SLEEPING HOURS");
        isSH = true;
    } else {
        System.out.println("NOT SLEEPING HOURS");
    }
    return isSH;
}

I am trying to test the method in Java environment like that:

public static void main(String[] args) {


Calendar calendar = Calendar.getInstance(Locale.UK);
    calendar.add(Calendar.DAY_OF_WEEK, -1);
    calendar.set(Calendar.HOUR_OF_DAY, 20);
    calendar.set(Calendar.MINUTE, 0);

    Date StartSH = calendar.getTime();
    calendar.add(Calendar.DAY_OF_WEEK, 2);
    calendar.set(Calendar.HOUR_OF_DAY, 9);
    calendar.set(Calendar.MINUTE, 45);

    Date StopSH = calendar.getTime();

    Date now = new Date(); // 9:42

    if (isWithingSH(StartSH, now, StopSH)) {
        System.out.println("SPEEPING HOURS");
    } else {
        System.out.println("NOT SPEEPING HOURS");
    }

}

The console displays NOT SLEEPING HOURS but I think it should say SLEEPING HOURS since it is before 9:30

halfer
  • 19,824
  • 17
  • 99
  • 186
Georgi Koemdzhiev
  • 11,421
  • 18
  • 62
  • 126

1 Answers1

4

If I understood correctly you only care about the hours/minutes so you could just check if the current hour is within the range provided by the user and in that case check if the minutes are within the minutes range

 public static boolean isWithingSH(Date startSH, Date now, Date stopSH) {
    try {
        SimpleDateFormat parser = new SimpleDateFormat("HH:mm", Locale.UK);
        Date startTime = parser.parse(startSH.getHours() + ":" + startSH.getMinutes());
        Date endTime = parser.parse(stopSH.getHours() + ":" + stopSH.getMinutes());
        Date nowTime = parser.parse(now.getHours() + ":" + now.getMinutes());

        if(startTime.after(endTime)) {
            if(endTime.after(nowTime)) {
                return true;
            } else {
                return false;
            }
        } else {
            if (startTime.before(nowTime) && endTime.after(nowTime)){
                return true;
            } else {
                return false;
            }
        }
    } catch (java.text.ParseException e) {
        return false;
    }
}

But I would lose Date (the methods you are using are deprecated) and use the jodatime library instead this question should hopefully give more light about pros/cons of using yodatime or any other 3rd party library

Community
  • 1
  • 1
  • Thank you for your answer. However. the method fails the check I have in the main method above :/ I called the method at 9:37 and the StopSH limit was set to 9:40 so it should have sayd sleeping hours still – Georgi Koemdzhiev Mar 03 '17 at 09:37
  • 1
    It fails because you are setting the hour_of_day as 40 instead of minutes ;) that makes the date as Mar 05 16:00 – Marcos Holgado Molina Mar 03 '17 at 09:41
  • Sorry. I corrected the test method and it still fails :/ – Georgi Koemdzhiev Mar 03 '17 at 09:45
  • 1
    Yes I was assuming 12 hour format, I have edited the answer with a new algorithm, it needs some cleanup (do not concatenate strings for instance). This one takes into account if the end time is lower than the start time so should work with 24h format. – Marcos Holgado Molina Mar 03 '17 at 10:03
  • Thank you again! Is there a way how I can set the year to be 2017 since currently startTime, endTime and nowTime as set the 1st of Jan -- 1970?. I think that is why the above check fails again (if I change the current time to be say 12:00 and the stopSH to be 11:00) – Georgi Koemdzhiev Mar 03 '17 at 11:15
  • 1
    You can just add the year on the SimpleDateFormat as "HH:mm yyyy" and adding the year when parsing the string but I can't see what that would be the issue. What are the start, end and now times that are failing? – Marcos Holgado Molina Mar 03 '17 at 11:26
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/137142/discussion-between-marcos-holgado-molina-and-georgi-koemdzhiev). – Marcos Holgado Molina Mar 03 '17 at 11:28
  • If the method count actually matters to you ;) – Marcos Holgado Molina Mar 05 '17 at 12:28