How to determine a date in between Friday and Sund

2020-02-16 03:03发布

问题:

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.

回答1:

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);
}


回答2:

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!!
}


回答3:

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;
  }