0

I'm trying to check a current date and time is in between Friday 17:42 and Sunday 17:42 of the week with Java.

At the moment I'm doing this with really really bad code block. It was a hurry solution. Now I'm refactoring but I couldn't find any method in joda or etc.

Any ideas? Thanks

private final Calendar currentDate = Calendar.getInstance();
private final int day = currentDate.get(Calendar.DAY_OF_WEEK);
private final int hour = currentDate.get(Calendar.HOUR_OF_DAY);
private final int minute = currentDate.get(Calendar.MINUTE);

if (day != 1 && day != 6 && day != 7) {
    if (combined != 0) {
        return badge == 1;
    } else {
        return badge == product;
    }
} else {
    if (day == 6 && hour > 16) {
        if (hour == 17 && minute < 43) {
            if (combined != 0) {
                return badge == 1;
            } else {
                return badge == product;
            }
        } else {
            return badge == 0;
        }
    } else if (day == 6 && hour < 17) {
        if (combined != 0) {
            return badge == 1;
        } else {
            return badge == product;
        }
    } else if (day == 1 && hour > 16) {
        if (hour == 17 && minute < 43) {
            return badge == 0;
        } else {
            if (combined != 0) {
                return badge == 1;
            } else {
                return badge == product;
            }
        }
    } else {
        return badge == 0;
    }
}

I've used the solution like thiswith the help of @MadProgrammer and @Meno Hochschild

Method:

public static boolean isBetween(LocalDateTime check, LocalDateTime startTime, LocalDateTime endTime) {
 return ((check.equals(startTime) || check.isAfter(startTime)) && (check.equals(endTime) || check.isBefore(endTime))); }

Usage:

static LocalDateTime now = LocalDateTime.now();
static LocalDateTime friday = now.with(DayOfWeek.FRIDAY).toLocalDate().atTime(17, 41);
static LocalDateTime sunday = friday.plusDays(2).plusMinutes(1);

if (!isBetween(now, friday, sunday)) { ... }

Thanks again for your efforts.

Taylan Derinbay
  • 128
  • 3
  • 13
  • Well, I might be look at `equals`, `before` and `after`... – MadProgrammer Jun 25 '15 at 08:21
  • 1
    Something like [this for example](http://stackoverflow.com/questions/25255811/start-date-and-end-date-between-two-dates/25255894#25255894) or [this for example](http://stackoverflow.com/questions/20677541/date-range-in-date-range/20678485#20678485) – MadProgrammer Jun 25 '15 at 08:23
  • One possible solution - Find "last Friday" and "next Sunday", calculate the difference between the, they should be 172800 seconds apart (yes, I calculated). If the difference between the two dates is not equal to 172800, you've not within those two dates... – MadProgrammer Jun 25 '15 at 08:55
  • Generally it is better to define your time range using the "Half-Open" approach where the beginning is *inclusive* while the ending is *exclusive*. So you would define the ending as the moment you *do not* want in your results, Sunday 17:43:00.0. Then compare ( >= beginning AND < ending ). One benefit is that you avoid problems with granularities of fractional second in various data sources, milliseconds, microseconds, or nanoseconds. – Basil Bourque Jun 25 '15 at 19:14

3 Answers3

4

Date and Calendar have methods that can perform comparisons on other instances of Date/Calendar, equals, before and after

However, I'd encourage the use of Java 8's new Time API

public static boolean isBetween(LocalDateTime check, LocalDateTime startTime, LocalDateTime endTime) {
    return ((check.equals(startTime) || check.isAfter(startTime)) && 
                    (check.equals(endTime) || check.isBefore(endTime)));
}

Which will return true if the supplied LocalDateTime is within the specified range inclusively.

Something like...

LocalDateTime start = LocalDateTime.now();
start = start.withDayOfMonth(26).withHour(17).withMinute(42).withSecond(0).withNano(0);
LocalDateTime end = start.plusDays(2);

LocalDateTime check = LocalDateTime.now();

System.out.println(check + " is within range = " + isBetween(check, start, end));
check = start;
System.out.println(check + " is within range = " + isBetween(check, start, end));
check = end;
System.out.println(check + " is within range = " + isBetween(check, start, end));
check = start.plusDays(1);
System.out.println(check + " is within range = " + isBetween(check, start, end));
check = end.plusMinutes(1);
System.out.println(check + " is within range = " + isBetween(check, start, end));

Which outputs

2015-06-25T18:31:32.969 is within range = false
2015-06-26T17:42 is within range = true
2015-06-28T17:42 is within range = true
2015-06-27T17:42 is within range = true
2015-06-28T17:43 is within range = false

Joda-Time has an Interval class which makes it even eaiser

Interval targetInterval = new Interval(targetStart, targetEnd);
System.out.println("Contains interval = " + interval.contains(targetInterval)

which is demonstrated here

A different approach...

So I was thinking on way home, assuming all you have is the date/time you want to check, how you might determine if the day falls within your range

LocalDateTime now = LocalDateTime.now();
boolean isBetween = false;
switch (now.getDayOfWeek()) {
    case FRIDAY:
    case SATURDAY:
    case SUNDAY:
        LocalDateTime lastFriday = getLastFriday(now);
        LocalDateTime nextSunday = getNextSunday(now);
        isBetween = isBetween(now, lastFriday, nextSunday);
        System.out.println(lastFriday + " - " + nextSunday + ": " + end);
        break;
}

What this does is checks the dayOfWeek to see if it's within the desired range, if it is, it finds the previous Friday and next Sunday from the specified date and checks to see if it falls between them (see the previous example)

lastFriday and nextSunday simply adds/subtracts a day from the specified date/time until to reaches the desired dayOfWeek, it then seeds the required time constraints

public static LocalDateTime getLastFriday(LocalDateTime anchor) {
    LocalDateTime ldt = LocalDateTime.from(anchor);
    return ldt.with(DayOfWeek.FRIDAY).withHour(17).withMinute(42).withSecond(0).withNano(0);
}

public static LocalDateTime getNextSunday(LocalDateTime anchor) {
    LocalDateTime ldt = LocalDateTime.from(anchor);
    return ldt.with(DayOfWeek.SUNDAY).withHour(17).withMinute(42).withSecond(0).withNano(0);
}
Community
  • 1
  • 1
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • +1 for your efforts. But are you sure that your code is equivalent to the old code posted by the OP? Consider for example the case now=Sunday-17:42:30. – Meno Hochschild Jun 25 '15 at 16:38
  • @MenoHochschild as far as I've tested, because a zero out the seconds and nano seconds, anything after 17:42 should fall outside the range, admittly, I tested for +1 minute (17:43) – MadProgrammer Jun 25 '15 at 20:51
  • Yes, 17:43 will fall out of the range. The point is that the original code of OP handles 17:42:30 slightly different (although this might be not the intention of the OP himself) so I tried to handle that in my answer, too. But probably he has not thought much about this tiny hair to split. I am also wondering why he uses such a time like 17:42 (and not for example 17:45) - use-case? – Meno Hochschild Jun 26 '15 at 05:08
  • @MenoHochschild I kind of skipped the code (as it was a mess) and went straight for *"Friday 17:42 and Sunday 17:42"* - nice to see the requirements don't meet the exceptions :P – MadProgrammer Jun 26 '15 at 05:11
  • @MenoHochschild It's for testing purposes. This code is a part of a selenium test. That's why I'm using 17:42, not 18:00 :) – Taylan Derinbay Jun 26 '15 at 06:21
0

With Calendar you can know what DAY_OF_WEEK is the given date, then simply check the hours:

Calendar c = Calendar.getInstance();
int dayOfWeek = c.get(Calendar.DAY_OF_WEEK);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);

// in friday the hour must be greater than 17:42
if (dayOfWeek == 5 && ((hour > 17) || (hour == 17 && minute >= 42)) {
    // successss!!
}
// days from 1 to 7... saturday(6) all day
if (dayOfWeek == 6) {
    // successss!!
}
// sunday hour must be lower than 17:42
if (dayOfWeek == 7 && ((hour < 17) || (hour == 17 && minute <= 42)) {
    // successss!!
}
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
0

A better solution using old Java would look like this:

// current timestamp
GregorianCalendar gcal = new GregorianCalendar();

// specify ISO-week (you are searching for friday until sunday in this order)
gcal.setMinimalDaysInFirstWeek(4);
gcal.setFirstDayOfWeek(Calendar.MONDAY);

// sunday at 17:43
GregorianCalendar sunday = (GregorianCalendar) gcal.clone();
sunday.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
sunday.set(Calendar.HOUR_OF_DAY, 17);
sunday.set(Calendar.MINUTE, 43);
sunday.set(Calendar.SECOND, 0);
sunday.set(Calendar.MILLISECOND, 0);

// friday at 17:42
GregorianCalendar friday = (GregorianCalendar) sunday.clone();
friday.add(Calendar.DATE, -2);
friday.add(Calendar.MINUTE, -1);

// logging for test purposes
SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS");
System.out.println(f.format(friday.getTime()));
System.out.println(f.format(gcal.getTime()));
System.out.println(f.format(sunday.getTime()));

// result (assumption: half-open-interval)
boolean withinTimeWindow = !gcal.before(friday) && gcal.before(sunday);

Java-8 offers a shorter approach (assuming ISO-weekmodel):

LocalDateTime now = LocalDateTime.now();
LocalDateTime friday = now.with(DayOfWeek.FRIDAY).toLocalDate().atTime(17, 42);
LocalDateTime sunday = friday.plusDays(2).plusMinutes(1);
boolean withinTimeWindow = !now.isBefore(friday) && now.isBefore(sunday);

Finally your equivalent evaluation can look like this:

  if (!withinTimeWindow) {
        if (combined != 0) {
            return badge == 1;
        } else {
            return badge == product;
        }
  } else {
        return badge == 0;
  }
Meno Hochschild
  • 42,708
  • 7
  • 104
  • 126