1

I'm looking to utilize GregorianCalendar to do some logic based on days. Is there any way to see if 2 dates are in the same week? I've tried using get(Calendar.WEEK_OF_YEAR), and this has the two downsides of:

1) Starting on the wrong day of the week (which seems to have a potential solution in setFirstDayOfWeek, however preliminary testing has not been successful.
2) This solution does not carry over years nicely. For example - Dec 30th, 2014 and Jan 1, 2015 should be in the same week.

Is there any solution to this that doesn't require switching libraries?

Zambezi
  • 767
  • 1
  • 9
  • 19
  • You need to get the start and end date of the week. You can then use Date.before and Date.after. You can use something like [this](http://stackoverflow.com/questions/2937086/how-to-get-the-first-day-of-the-current-week-and-month) to get the date boundaries – MadProgrammer Mar 24 '15 at 21:15
  • Quick question - is there going to be a time component to these dates? If not, you could just subtract off the number of days given by the DAY_OF_WEEK field and compare them. – Dawood ibn Kareem Mar 24 '15 at 21:29
  • Have you considered looking at `cal.get(Calendar.WEEK_OF_YEAR)`? – MadProgrammer Mar 25 '15 at 00:02
  • @MadProgrammer If you read the question, you'll see that OP has considered using `get(Calendar.WEEK_OF_YEAR)`, and found two reasons to reject it. – Dawood ibn Kareem Mar 25 '15 at 00:51
  • @DavidWallace Then I back to my first comment – MadProgrammer Mar 25 '15 at 01:20
  • @DavidWallace - there will be a time component on these dates (the times are used in other places) but the times are not significant for me when it comes to determining the week it is in. – Zambezi Mar 25 '15 at 13:49

2 Answers2

1

You question basically boils down to determining if a given date falls within a given date range (ie a week).

The idea behind this is basically one of the two date's acts as the anchor, from which we calculate the date range (start of week to end of week) and then determine if the other date falls within that range.

So, first, we need to calculate the date range, something like...

Calendar cal = Calendar.getInstance();
cal.setTime(date1);
cal.set(Calendar.HOUR_OF_DAY, 0); 
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);

cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
Date startOfWeek = cal.getTime();

cal.add(Calendar.DATE, 6);
cal.set(Calendar.HOUR_OF_DAY, 23); 
cal.set(Calendar.MINUTE, 59); 
cal.set(Calendar.SECOND, 59); 
cal.set(Calendar.MILLISECOND, 999); 
Date endOfWeek = cal.getTime();

Which will give us two dates, the first starting at the "start of the week" and one 6 days later (the "end of the week"). We force the time values to the extreme of the days to ensure we can capture the fall range

Next, we need to determine if the other date is equal to or after the "start of the week" and equal to or before the "end of the week", something like...

(date2.equals(startOfWeek) || date2.after(startOfWeek)) && (date2.equals(endOfWeek) || date2.before(endOfWeek));

This could then be wrapped up in a nice little method to make calling it simpler...

public static boolean isInSameWeek(Date date1, Date date2) {
    Calendar cal = Calendar.getInstance();
    cal.setTime(date1);
    cal.set(Calendar.HOUR_OF_DAY, 0);
    cal.clear(Calendar.MINUTE);
    cal.clear(Calendar.SECOND);
    cal.clear(Calendar.MILLISECOND);

    cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek());
    Date startOfWeek = cal.getTime();

    cal.add(Calendar.DATE, 6);
    cal.set(Calendar.HOUR_OF_DAY, 23);
    cal.set(Calendar.MINUTE, 59);
    cal.set(Calendar.SECOND, 59);
    cal.set(Calendar.MILLISECOND, 999);
    Date endOfWeek = cal.getTime();

    System.out.println("Week starts at : " + startOfWeek);
    System.out.println("  Week ends at : " + endOfWeek);

    return (date2.equals(startOfWeek) || date2.after(startOfWeek)) && (date2.equals(endOfWeek) || date2.before(endOfWeek));

}

And then we can test it...

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/yyyy");
try {
    Date date1 = sdf.parse("30/12/2014");
    Date date2 = sdf.parse("1/1/2015");

    System.out.println("Is in same week " + date1 + "/" + date2 + " = " + isInSameWeek(date1, date2));
    System.out.println("");

    date1 = sdf.parse("27/12/2014");
    System.out.println("Is in same week " + date1 + "/" + date2 + " = " + isInSameWeek(date1, date2));
} catch (ParseException exp) {
    exp.printStackTrace();
}

Which outputs something like...

Week starts at : Sun Dec 28 00:00:00 EST 2014
  Week ends at : Sat Jan 03 23:59:59 EST 2015
Is in same week Tue Dec 30 00:00:00 EST 2014/Thu Jan 01 00:00:00 EST 2015 = true

Week starts at : Sun Dec 21 00:00:00 EST 2014
  Week ends at : Sat Dec 27 23:59:59 EST 2014
Is in same week Sat Dec 27 00:00:00 EST 2014/Thu Jan 01 00:00:00 EST 2015 = false
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • @DavidWallace It's essentially what it's doing. Instead of checking to see if the `date` "falls" into same range, you are checking to see if the `start of week` for both values is the same. At the end of the day, you still have almost the same amount of work, this is just how I saw the problem. It also (crudely) demonstrates a simple date range checking algorithm, which could be further expanded and plugged into this code to reduce duplication...but that's beyond the answer. Me, personally, I'd be looking towards JodaTime or some other time API, but that's me – MadProgrammer Mar 25 '15 at 04:14
  • @DavidWallace Remember, I also broke this down into a "date range" issue, that's just how I saw it :P – MadProgrammer Mar 25 '15 at 04:16
  • @DavidWallace I don't discount there are better ways to doing it, I just saw it as a "date range" issue. It "might" help the OP recognize ways to solver other problems, it might not :P – MadProgrammer Mar 25 '15 at 04:18
1

OK, since you've stated there will be a time component, I'd use something similar to @MadProgrammer's answer, but without the complexity of using an entire date range. I'd have a static method something like this.

public static Date firstOfWeek(Calendar cal) {
    Calendar copy = new GregorianCalendar( 
        cal.get(Calendar.YEAR), cal.get(Calendar.MONTH), cal.get(Calendar.DATE));
    copy.set(Calendar.DAY_OF_WEEK, copy.getFirstDayOfWeek());
    return copy.getTime();
}

This returns a Date for the first day of the week that includes a particular Calendar. You can then check whether two calendars fall in the same week like this.

if (firstOfWeek(cal1).equals(firstOfWeek(cal2))) {
    ...
}
Dawood ibn Kareem
  • 77,785
  • 15
  • 98
  • 110