0

Im trying to check if a given date is within a range between Sunday 10pm to Friday 10pm

I want to use the Calendar to achieve this and I've written a small bit of the code which is logically incorrect. I'd appreciate some help here

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(lastTickTime);
calendar.setTimeZone(TimeZone.getTimeZone("GMT"));

int currentHour = calendar.get(Calendar.HOUR_OF_DAY);
int currentDay = calendar.get(Calendar.DAY_OF_WEEK);

int fromDay = 1;
int toDay = 6;

int fromHour = 22;
int toHour = 22;

boolean result = (currentDay <= fromDay && currentHour < fromHour) || (currentDay >= toDay && currentHour > toHour);

I know the above approach is not right and Im unsure on how to go about it. Thanks

Salman Fazal
  • 559
  • 7
  • 22
  • 2
    If you can, try to use the new java time API. Here's an [introduction](https://www.baeldung.com/java-8-date-time-intro). – Reto Höhener Dec 25 '20 at 09:12
  • Do you mean: if the day is Sunday, the result is true if the time is 10pm or later, on Monday to Thursday it is always true and on Friday it is true if the time is before 10pm? – Thomas Kläger Dec 25 '20 at 09:53
  • A date (and time) is **not** valid if it is after Friday 10 pm and before Sunday 10 pm. Every other day of the week (and hour) is valid. Is that correct? In other words, the weekend is basically invalid, right? – Abra Dec 25 '20 at 10:03
  • @ThomasKläger so basically, return true if its between Friday 10pm to Sunday 10pm – Salman Fazal Dec 25 '20 at 10:06
  • @Abra you're almost right, weekend is invalid but its from Fri 10pm - Sun 10pm – Salman Fazal Dec 25 '20 at 10:07

1 Answers1

3

Update:

I just saw that you have metioned the following in your comment:

return true if its between Friday 10pm to Sunday 10pm

which is completely different from what you have mentioned (given below) in your question:

Im trying to check if a given date is within a range between Sunday 10pm to Friday 10pm

I have already provided you with the solution to check a date-time between Sunday 10pm to Friday 10pm (check the section, Original solution).

Given below is the solution for a date-time between Friday 10pm to Sunday 10pm of a week:

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(isValidTime("2020-12-25T09:38:08", "America/Chicago"));// Should be false
        System.out.println(isValidTime("2020-12-25T22:38:08", "America/Chicago"));// Should be true
        System.out.println(isValidTime("2020-12-26T09:38:08", "America/Chicago"));// Should be true
        System.out.println(isValidTime("2020-12-27T09:38:08", "America/Chicago"));// Should be true
        System.out.println(isValidTime("2020-12-27T22:38:08", "America/Chicago"));// Should be false
    }

    static boolean isValidTime(String strDateTime, String timezone) {
        ZoneId zoneId = ZoneId.of(timezone);
        ZonedDateTime zdt = LocalDateTime.parse(strDateTime).atZone(zoneId).withZoneSameInstant(ZoneOffset.UTC);
        ZonedDateTime fri10Pm = zdt.with(ChronoField.DAY_OF_WEEK, DayOfWeek.FRIDAY.getValue())
                .with(LocalTime.of(22, 0));
        ZonedDateTime sun10Pm = zdt.with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue())
                .with(LocalTime.of(22, 0));
        return zdt.isAfter(fri10Pm) && zdt.isBefore(sun10Pm);
    }
}

Output:

false
true
true
true
false

Original solution:

With java.time (the modern date-time API):

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoField;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(isValidTime("2020-12-25T09:38:08", "America/Chicago"));// Should be true
        System.out.println(isValidTime("2020-12-26T09:38:08", "America/Chicago"));// Should be false
        System.out.println(isValidTime("2020-12-27T09:38:08", "America/Chicago"));// Should be false
        System.out.println(isValidTime("2020-12-27T22:38:08", "America/Chicago"));// Should be true
        System.out.println(isValidTime("2021-01-01T09:38:08", "America/Chicago"));// Should be true
        System.out.println(isValidTime("2021-01-01T23:38:08", "America/Chicago"));// Should be false
    }

    static boolean isValidTime(String strDateTime, String timezone) {
        ZoneId zoneId = ZoneId.of(timezone);
        ZonedDateTime zdt = LocalDateTime.parse(strDateTime).atZone(zoneId).withZoneSameInstant(ZoneOffset.UTC);
        ZonedDateTime temp = zdt.getDayOfWeek() != DayOfWeek.SUNDAY ? zdt.minusWeeks(1) : zdt;
        ZonedDateTime sun10Pm = temp.with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue())
                .with(LocalTime.of(22, 0));
        ZonedDateTime fri10PmNextWeek = temp.plusWeeks(1).with(ChronoField.DAY_OF_WEEK, DayOfWeek.FRIDAY.getValue())
                .with(LocalTime.of(22, 0));
        return zdt.isAfter(sun10Pm) && zdt.isBefore(fri10PmNextWeek);
    }
}

Output:

true
false
false
true
true
false

The solution is based on the following assumptions and you should adjust it in case of a deviation from any of these assumptions:

  1. You want to compare date-time in UTC. The solution parses the date-time string as local date-time (a date-time without any timezone information) and then converts it into the ZonedDateTime of the timezone where the date-time belongs. Finally, this ZonedDateTime is converted to a date-time in UTC.
  2. If the date-time does not fall on Sun, the comparison should be done on a date from the last Sun to the coming Fri.
  3. The time of 10 pm is not inclusive.

Appendix:

If you do not have to deal with timezone and you want to simply check if the given date-time is between Fri 10 pm and Sun 10 pm, you can do it using LocalDateTime.

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.temporal.ChronoField;

public class Main {
    public static void main(String[] args) {
        // Test
        System.out.println(isValidTime("2020-12-25T09:38:08"));// Should be false
        System.out.println(isValidTime("2020-12-25T22:38:08"));// Should be true
        System.out.println(isValidTime("2020-12-26T09:38:08"));// Should be true
        System.out.println(isValidTime("2020-12-27T09:38:08"));// Should be true
        System.out.println(isValidTime("2020-12-27T22:38:08"));// Should be false
    }

    static boolean isValidTime(String strDateTime) {
        LocalDateTime ldt = LocalDateTime.parse(strDateTime);
        LocalDateTime fri10Pm = ldt.with(ChronoField.DAY_OF_WEEK, DayOfWeek.FRIDAY.getValue())
                .with(LocalTime.of(22, 0));
        LocalDateTime sun10Pm = ldt.with(ChronoField.DAY_OF_WEEK, DayOfWeek.SUNDAY.getValue())
                .with(LocalTime.of(22, 0));
        return ldt.isAfter(fri10Pm) && ldt.isBefore(sun10Pm);
    }
}

Output:

false
true
true
true
false

Using legacy API:

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;

public class Main {
    public static void main(String[] args) throws ParseException {
        // Test
        System.out.println(isValidTime("2020-12-25T09:38:08"));// Should be false
        System.out.println(isValidTime("2020-12-25T22:38:08"));// Should be true
        System.out.println(isValidTime("2020-12-26T09:38:08"));// Should be true
        System.out.println(isValidTime("2020-12-27T09:38:08"));// Should be true
        System.out.println(isValidTime("2020-12-27T22:38:08"));// Should be false
    }

    static boolean isValidTime(String strDateTime) throws ParseException {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
        Date date = sdf.parse(strDateTime);

        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 22);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        Date fri10Pm = calendar.getTime();

        calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
        calendar.set(Calendar.HOUR_OF_DAY, 22);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);

        Date sun10Pm = calendar.getTime();

        return date.after(fri10Pm) && date.before(sun10Pm);
    }
}

Output:

false
true
true
true
false

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • Great and thorough answer. Rather than `.withHour(22).withMinute(0).withSecond(0).withNano(0)` I’d prefer `.with(LocalTime.of(22, 0))`. Yes, you can use the date-time types as temporal adjusters too, I find it pretty neat. – Ole V.V. Dec 25 '20 at 16:52
  • Thanks, @OleV.V. for the valuable feedback. I was actually looking for it but somehow I could not find it at the time of writing the answer. I've incorporated this into the answer now. – Arvind Kumar Avinash Dec 25 '20 at 16:58
  • This was a very detailed and valuable answer, I really appreciate your time and help! – Salman Fazal Dec 27 '20 at 04:57