5

What is most convenient and shortest way to get start and end dates of the previous week? Example: today is 2011-10-12 (input data),but I want to get 2011-10-03 (Monday's date of previous week) and 2011-10-09 (Sunday's date of previous week).

adrift
  • 637
  • 2
  • 10
  • 34

6 Answers6

6

Here's another JodaTime solution. Since you seem to want Dates only (not timestamps), I'd use the DateMidnight class:

final DateTime input = new DateTime();
System.out.println(input);
final DateMidnight startOfLastWeek = 
    new DateMidnight(input.minusWeeks(1).withDayOfWeek(DateTimeConstants.MONDAY));
System.out.println(startOfLastWeek);
final DateMidnight endOfLastWeek = startOfLastWeek.plusDays(6);
System.out.println(endOfLastWeek);

Output:

2011-10-12T18:13:50.865+02:00
2011-10-03T00:00:00.000+02:00
2011-10-10T00:00:00.000+02:00
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
  • And if your week is not Monday to Sunday? – jarnbjo Oct 12 '11 at 16:20
  • 1
    @jarnbjo what a strange reason to downvote. why not just ask? anyway, I changed the code to use the constant for monday. How to change it to sunday should be rather obvious now. BTW, out of curiosity: who's week doesn't start on monday? – Sean Patrick Floyd Oct 12 '11 at 16:29
  • 1
    This is the shortest solution. I've already implemented, thanks a lot! – adrift Oct 12 '11 at 17:17
  • @Sean: In North America, the week starts on Sunday and ends on Saturday. In most Arabic speaking countries, the week starts on Saturday and ends on Friday. – jarnbjo Oct 12 '11 at 18:44
  • @jarnbjo: I do not care about handling multiple locales this time. It wasn't in the scope of question. – adrift Oct 12 '11 at 18:49
  • @Sean: BTW, it is not at all obvious how to change your code to cope with these differences, since Joda does not implement the concept of localized week boundaries. Changing the constant DateTimeConstants.MONDAY to DateTimeConstants.SUNDAY will simply set startOfLastWeek to the previous Sunday, e.g. that what Joda claims to be the Sunday in the previous week. – jarnbjo Oct 12 '11 at 18:51
  • @Viktors: "I do not care about " is a very dangerous statement when dealing with dates and time. Are you the kind of developer who assumes that all days have 24 hours, all months 30 days and all years 365 days? That's also mostly correct. – jarnbjo Oct 12 '11 at 18:54
  • The program is correct, but the output is wrong. End of the week should be 2011-10-09 not 2011-10-10, otherwise it would be eight days a week ;) – martin Oct 13 '11 at 12:06
  • 1
    @martin well, that's a [great song](http://www.youtube.com/watch?v=YtuybFrq7Rw), after all – Sean Patrick Floyd Oct 13 '11 at 13:39
  • 1
    The midnight-related classes and methods have been deprecated in Joda-Time. Use the `withTimeAtStartOfDay` method on DateTime instead. – Basil Bourque Aug 02 '15 at 05:40
  • @BasilBourque that's the problem with SO answers, they become obsolete after a few years. Feel free to add an appropriate answer – Sean Patrick Floyd Aug 02 '15 at 21:13
4
public static Calendar firstDayOfLastWeek(Calendar c) {
    c = (Calendar) c.clone();
    // last week
    c.add(Calendar.WEEK_OF_YEAR, -1);
    // first day
    c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
    return c;
}

public static Calendar lastDayOfLastWeek(Calendar c) {
    c = (Calendar) c.clone();
    // first day of this week
    c.set(Calendar.DAY_OF_WEEK, c.getFirstDayOfWeek());
    // last day of previous week
    c.add(Calendar.DAY_OF_MONTH, -1);
    return c;
}
jarnbjo
  • 33,923
  • 7
  • 70
  • 94
2

I would go for @maerics answer if third party library is not involved. I have to replace roll() method with add() method as roll will leave the higher field unchanged. e.g., 22nd August will be obtained from 1st August being rolled -7 days. Note the month remain unchanged. The source code goes as below.

public static Calendar[] getLastWeekBounds(Calendar c) {
  int cdow = c.get(Calendar.DAY_OF_WEEK);
  Calendar lastMon = (Calendar) c.clone();
  lastMon.add(Calendar.DATE, -7 - (cdow - Calendar.MONDAY));
  Calendar lastSun = (Calendar) lastMon.clone();
  lastSun.add(Calendar.DATE, 6);
  return new Calendar[] { lastMon, lastSun };
}
ZJ Lyu
  • 331
  • 3
  • 10
0

You can use the Calendar.roll(int,int) method with arguments Calendar.DATE and an offset for the current day of week:

public static Calendar[] getLastWeekBounds(Calendar c) {
  int cdow = c.get(Calendar.DAY_OF_WEEK);
  Calendar lastMon = (Calendar) c.clone();
  lastMon.roll(Calendar.DATE, -7 - (cdow - Calendar.MONDAY));
  Calendar lastSun = (Calendar) lastMon.clone();
  lastSun.roll(Calendar.DATE, 6);
  return new Calendar[] { lastMon, lastSun };
}

This function returns an array of two Calendars, the first being last week's Monday and last week's Sunday.

Wow, the Java date APIs are terrible.

maerics
  • 151,642
  • 46
  • 269
  • 291
  • That's why many people prefer to use a third-party library to handle date and time in Java. – martin Oct 12 '11 at 15:51
-1

Using Joda:

DateTime input;
DateTime startOfLastWeek = input.minusWeeks(1).minusDays(input.getDayOfWeek()-1);

DateTime endOfLastWeek = input.minusWeeks(1).plusDays(input.getDayOfWeek()+1);

DateTime endOfLastWeek = startOfLastWeek.plusDays(6);

EDIT:

Joda does not allow a different first day of the week, but strictly sticks to the ISO standard, which states that a week always starts on Monday. However, if you need to make that configurable, you could pass the desired first day of the week as a parameter. See the above link for some other ideas.

public DateTime getFirstDayOfPreviousWeek(DateTime input)
{
    return getFirstDayOfPreviousWeek(input, DateTimeConstants.MONDAY); 
}

public DateTime getFirstDayOfPreviousWeek(DateTime input, int firstDayOfWeek)
{
    return new DateTime(input.minusWeeks(1).withDayOfWeek(firstDayOfWeek));
}

public DateTime getLastDayOfPreviousWeek(DateTime input)
{
    return getLastDayOfPreviousWeek(input, DateTimeConstants.MONDAY); 
}

public DateTime getLastDayOfPreviousWeek(DateTime input, int firstDayOfWeek)
{
    return new DateTime(getFirstDayOfPreviousWeek(input, firstDayOfWeek).plusDays(6));
}
Community
  • 1
  • 1
martin
  • 2,150
  • 1
  • 34
  • 48
  • DateTime has a constructor taking a java.util.Calendar-object, so you could use it like this: DateTime input = new DateTime(calendar); – martin Oct 12 '11 at 15:35
  • 2
    This is utterly wrong. endOflastWeek is always off, except perhaps on Wednesdays and the code does not honour locale-specific rules regarding which week day is the first. – jarnbjo Oct 12 '11 at 16:00
  • That's right, I posted the wrong version. Fixed that. As for different first days of the week (e.g. Sunday), that's pretty obvious to change and it should be no problem to make it configurable. – martin Oct 13 '11 at 12:03
-1
Calendar today  = Calendar.getInstance();
Calendar lastWeekSunday =  (today.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) ? today.roll(-7): today.roll(Calendar.DAY_OF_YEAR, Calendar.SUNDAY - today.get(Calendar.DAY_OF_WEEK));
Calendar lastWeekMonday = lastWeekSunday.roll( Calendar.DAY_OF_YEAR, -6 );
kingori
  • 2,406
  • 27
  • 30