views:

187

answers:

7

Hi,

Given an instance of java.util.Date which is a Sunday. If there are 4 Sundays in the month in question, I need to figure out whether the chosen date is

  • 1st Sunday of month
  • 2nd Sunday of month
  • 2nd last Sunday of month
  • Last Sunday of month

If there are 5 Sundays in the month in question, then I need to figure out whether the chosen date is

  • 1st Sunday of month
  • 2nd Sunday of month
  • 3rd Sunday of month
  • 2nd last Sunday of month
  • Last Sunday of month

I've had a look in JodaTime, but haven't found the relevant functionality there yet. The project is actually a Groovy project, so I could use either Java or Groovy to solve this.

Thanks, Donal

+1  A: 

int sundayOfMonth = dayOfMonth / 7 + 1;

glowcoder
Should that be div rather than mod? 3 % 7 gives 3, 3 / 7 gives 0.
Vincent Ramdhanie
Yep - changed. Thanks Vincent
glowcoder
+2  A: 

DAY_OF_WEEK_IN_MONTH

import java.sql.Date;
import java.util.Calendar;

public class Dow {
    public static void main(String[] args) {
        Date date = new Date( 2010, 4, 1 );
        Calendar cal = Calendar.getInstance();
        cal.setTime( date );
        for ( int week = 0 ; week < 5 ; week++ ) {
            System.out.println( cal.getTime() + " week:" + cal.get( Calendar.DAY_OF_WEEK_IN_MONTH ) );
            cal.add( Calendar.WEEK_OF_MONTH, 1 );
        }
    }
}


> Sun May 01 00:00:00 CEST 3910 week:1
> Sun May 08 00:00:00 CEST 3910 week:2
> Sun May 15 00:00:00 CEST 3910 week:3
> Sun May 22 00:00:00 CEST 3910 week:4
> Sun May 29 00:00:00 CEST 3910 week:5
stacker
Just a small remark: that's not exactly a week number you print. For example, if week starts on Sunday and 2010-05-02 is Sunday, isn't it a second week of month already?
hudolejev
@hudolejev Your right it's call ordinal number, as descibed in the linked javadoc.
stacker
+2  A: 
return dayOfMonth / 7 + 1;

MORE EDIT

Okay, taking Jay's comment in consideration, let's try this one:

int sundayId = dayOfMonth / 7 + 1;
if (sundayId == 1) {
    return "1st";
} else if (sundayId == 2) {
    return "2nd";
} else if (sundayId == 3) {
    return ((dayOfMonth + 14 <= daysInMonth) ? "3rd" : "2nd Last");
} else if (sundayId == 4) {
    return ((dayOfMonth + 7 <= daysInMonth) ? "2nd Last" : "Last");
} else {
    return "Last";
}

whereas daysInMonth is calculated as follows:

if (month == 2) {
    if (year % 100) {
        return ((year % 400 == 0) ? 29 : 28);
    } else {
        return ((year % 4 == 0) ? 29 : 28);
    }
} else if (month == 4 || month == 6 || month == 9 || month == 11) {
    return 30;
} else {
    return 31;
}

... or in some other way.

hudolejev
Sorry, forgot about +1.
hudolejev
Ah, the +14, +7, pretty clean solution. Not bad.
Jay
A: 

for any date manipulaton, i strongly suggest joda-time...its lot easier and performant

Pangea
+1  A: 

You can just use java.util.Calendar to do your date calculations:

import java.util.Calendar as CAL

def cal = CAL.getInstance(date)
def isFirst= cal.get(CAL.WEEK_OF_MONTH) == 1
def isSecond = cal.get(CAL.WEEK_OF_MONTH) == cal.getMaximum(CAL.WEEK_OF_MONTH)

Also, do not assume that there are only five weeks in a month with the Calendar object. For instance, the maximum weeks of 05/01/2010 would be 6.

Eric Hauser
Still impossible to have 6 Sundays. The question is 'how to get the Sunday #', not 'how to get week #' if I got it right.
hudolejev
+4  A: 

Solutions given so far will tell you 1st, 2nd, 3rd, 4th, or 5th. But the question said he wanted to know "last" and "second to last". If the questioner really needs to know "last" etc, there's a little extra complexity. You have to figure out how many Sundays are in the month to know whether or not the 4th Sunday is the last. The first way to figure that out that occurs to me is:

GregorianCalendar gc=new GregorianCalendar();
gc.setTime(mydate);
gc.set(Calendar.DAY_OF_MONTH,1); // Roll back to first of month
int weekday=gc.get(Calendar.DAY_OF_WEEK); // day of week of first day
// Find day of month of first Sunday
int firstSunday;
if (weekday==Calendar.SUNDAY)
  firstSunday=1;
else
  firstSunday=weekday-Calendar.SUNDAY+6;
// Day of month of fifth Sunday, if it exists
int fifthSunday=firstSunday+7*4;
// Find last day of month
gc.add(Calendar.MONTH,1);
gc.add(Calendar.DATE,-1);
int lastDay=gc.get(DAY_OF_MONTH);

int sundays;
if (fifthSunday<lastDay)
  sundays=4;
else
  sundays=5;

That seems like rather a lot of work. Anybody see an easier way?

Jay
Thanks Jay, seems like you're the only person who read the entire question
Don
A: 

EDIT: Here's my final version:

today = Calendar.instance
dayOfWeekInMonth = today.get(Calendar.DAY_OF_WEEK_IN_MONTH)

// move to last day of week occurrence in current month
today.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1)
maxDayOfWeekInMonth = today.get(Calendar.DAY_OF_WEEK_IN_MONTH)

dayOfWeekCount = ["1st", "2nd", "3rd", "2nd last", "Last"]

turningPoint = maxDayOfWeekInMonth - 2
if (dayOfWeekInMonth <= turningPoint) {
  println dayOfWeekCount[dayOfWeekInMonth - 1]
}
else {
  // use negative index to access list from last to first
  println dayOfWeekCount[dayOfWeekInMonth - maxDayOfWeekInMonth - 1]
}
Christoph Metzendorf