Reputation: 5943
I am working on a project where the requirement is to have a date calculated as being the last Friday of a given month. I think I have a solution that only uses standard Java, but I was wondering if anyone knew of anything more concise or efficient. Below is what I tested with for this year:
for (int month = 0; month < 13; month++) {
GregorianCalendar d = new GregorianCalendar();
d.set(d.MONTH, month);
System.out.println("Last Week of Month in " + d.getDisplayName(d.MONTH, Calendar.LONG, Locale.ENGLISH) + ": " + d.getLeastMaximum(d.WEEK_OF_MONTH));
d.set(d.DAY_OF_WEEK, d.FRIDAY);
d.set(d.WEEK_OF_MONTH, d.getActualMaximum(d.WEEK_OF_MONTH));
while (d.get(d.MONTH) > month || d.get(d.MONTH) < month) {
d.add(d.WEEK_OF_MONTH, -1);
}
Date dt = d.getTime();
System.out.println("Last Friday of Last Week in " + d.getDisplayName(d.MONTH, Calendar.LONG, Locale.ENGLISH) + ": " + dt.toString());
}
Upvotes: 19
Views: 36124
Reputation: 7466
Using java.time library built into Java 8 and later, you may use TemporalAdjusters.lastInMonth
:
val now = LocalDate.now()
val lastInMonth = now.with(TemporalAdjusters.lastInMonth(DayOfWeek.FRIDAY))
You may choose any day from the DayOfWeek
enum.
If you need to add time information, you may use any available LocalDate
to LocalDateTime
conversion like
lastFriday.atStartOfDay() // e.g. 2015-11-27T00:00
Upvotes: 19
Reputation: 13845
In Java 8, we can do it simply as:
LocalDate lastFridayOfMonth = LocalDate
.now()
.with(lastDayOfMonth())
.with(previous(DayOfWeek.FRIDAY));
Upvotes: 1
Reputation:
Hope this helps..
public static void getSundaysInThisMonth(int monthNumber, int yearNumber){
//int year =2009;
//int dayOfWeek = Calendar.SUNDAY;
// instantiate Calender and set to first Sunday of 2009
Calendar cal = new GregorianCalendar();
cal.set(Calendar.MONTH, monthNumber-1);
cal.set(Calendar.YEAR, yearNumber);
cal.set(Calendar.DATE, 1);
int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
int dateOfWeek = cal.get(Calendar.DATE);
while (dayOfWeek != Calendar.SUNDAY) {
cal.set(Calendar.DATE, ++dateOfWeek);
dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
}
cal.set(Calendar.DATE, dateOfWeek);
int i = 1;
while (cal.get(Calendar.YEAR) == yearNumber && cal.get(Calendar.MONTH)==monthNumber-1)
{
System.out.println("Sunday " + " " + i + ": " + cal.get(Calendar.DAY_OF_MONTH));
cal.add(Calendar.DAY_OF_MONTH, 7);
i++;
}
}
public static void main(String args[]){
getSundaysInThisMonth(1,2009);
}
Upvotes: 0
Reputation: 1
public static int lastSundayDate()
{
Calendar cal = getCalendarInstance();
cal.setTime(new Date(getUTCTimeMillis()));
cal.set( Calendar.DAY_OF_MONTH , 25 );
return (25 + 8 - (cal.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY ? cal.get(Calendar.DAY_OF_WEEK) : 8));
}
Upvotes: 0
Reputation: 11
Below program is for the last Friday of each month. it can be used to get the last of any day of the week in any month. The variable offset=0
means current month(system date), offset=1 means next month, so on. The getLastFridayofMonth(int offset)
method will return the last Friday.
import java.text.SimpleDateFormat;
import java.util.Calendar;
public class LastFriday {
public static Calendar getLastFriday(Calendar cal,int offset){
int dayofweek;//1-Sunday,2-Monday so on....
cal.set(Calendar.MONTH,cal.get(Calendar.MONTH)+offset);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); //set calendar to last day of month
dayofweek=cal.get(Calendar.DAY_OF_WEEK); //get the day of the week for last day of month set above,1-sunday,2-monday etc
if(dayofweek<Calendar.FRIDAY) //Calendar.FRIDAY will return integer value =5
cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH)-7+Calendar.FRIDAY-dayofweek);
else
cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH)+Calendar.FRIDAY-dayofweek);
return cal;
}
public static String getLastFridayofMonth(int offset) { //offset=0 mean current month
final String DATE_FORMAT_NOW = "dd-MMM-yyyy";
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
cal=getLastFriday(cal,offset);
return sdf.format(cal.getTime());
}
public static void main(String[] args) {
System.out.println(getLastFridayofMonth(0)); //0 = current month
System.out.println(getLastFridayofMonth(1));//1=next month
System.out.println(getLastFridayofMonth(2));//2=month after next month
}
}
Upvotes: 1
Reputation: 39
public static Calendar getNthDow(int month, int year, int dayOfWeek, int n) {
Calendar cal = Calendar.getInstance();
cal.set(year, month, 1);
cal.set(Calendar.DAY_OF_WEEK, dayOfWeek);
cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, n);
return (cal.get(Calendar.MONTH) == month) && (cal.get(Calendar.YEAR) == year) ? cal : null;
}
Upvotes: -1
Reputation: 8304
here's how to get the last friday, or whatever week day, of the month:
Calendar thisMonth = Calendar.getInstance();
dayOfWeek = Calendar.FRIDAY; // or whatever
thisMonth.set(Calendar.WEEK_OF_MONTH, thisMonth.getActualMaximum(Calendar.WEEK_OF_MONTH);;
thisMonth.set(Calendar.DAY_OF_WEEK, dayOfWeek);
int lastDay = thisMonth.get(Calendar.DAY_OF_MONTH); // this should be it.
Upvotes: 2
Reputation:
Let Calendar.class do its magic for you ;)
pCal.set(GregorianCalendar.DAY_OF_WEEK,Calendar.FRIDAY);
pCal.set(GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1);
Upvotes: 38
Reputation: 881
code for Adam Davis's algorithm
public static int getLastFriday(int month, int year)
{
Calendar cal = Calendar.getInstance();
cal.set(year, month, 1, 0, 0, 0); // set to first day of the month
cal.set(Calendar.MILLISECOND, 0);
int firstDay = cal.get(Calendar.DAY_OF_WEEK);
int daysOfMonth = cal.getMaximum(Calendar.DAY_OF_MONTH);
switch (firstDay)
{
case Calendar.SUNDAY :
return 27;
case Calendar.MONDAY :
return 26;
case Calendar.TUESDAY :
return 25;
case Calendar.WEDNESDAY :
if (daysOfMonth == 31) return 31;
return 24;
case Calendar.THURSDAY :
if (daysOfMonth >= 30) return 30;
return 23;
case Calendar.FRIDAY :
if (daysOfMonth >= 29) return 29;
return 22;
case Calendar.SATURDAY :
return 28;
}
throw new RuntimeException("what day of the month?");
}}
Upvotes: 2
Reputation: 93565
You need to know two things - the number of days in the month, and the weekday the first of the month falls on.
If the first day of the month is a
There are only three special cases. A single switch statement and three if statements (or ternary operators if you like every case to have a single line...)
Work it out on paper. Don't need any special libraries, functions, julian conversions, etc (well, except to get the weekday the 1st falls on, and maybe the number of days that month... )
-Adam
Upvotes: 2
Reputation: 110054
Based on marked23's suggestion:
public Date getLastFriday( int month, int year ) {
Calendar cal = Calendar.getInstance();
cal.set( year, month + 1, 1 );
cal.add( Calendar.DAY_OF_MONTH, -( cal.get( Calendar.DAY_OF_WEEK ) % 7 + 1 ) );
return cal.getTime();
}
Upvotes: 27
Reputation: 13779
Slightly easier to read, brute-force approach:
public int getLastFriday(int month, int year) {
Calendar cal = Calendar.getInstance();
cal.set(year, month, 1, 0, 0, 0); // set to first day of the month
cal.set(Calendar.MILLISECOND, 0);
int friday = -1;
while (cal.get(Calendar.MONTH) == month) {
if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { // is it a friday?
friday = cal.get(Calendar.DAY_OF_MONTH);
cal.add(Calendar.DAY_OF_MONTH, 7); // skip 7 days
} else {
cal.add(Calendar.DAY_OF_MONTH, 1); // skip 1 day
}
}
return friday;
}
Upvotes: 1
Reputation: 1826
I would use a library like Jodatime. It has a very useful API and it uses normal month numbers. And best of all, it is thread safe.
I think that you can have a solution with (but possibly not the shortest, but certainly more readable):
DateTime now = new DateTime();
DateTime dt = now.dayOfMonth().withMaximumValue().withDayOfWeek(DateTimeConstants.FRIDAY);
if (dt.getMonthOfYear() != now.getMonthOfYear()) {
dt = dt.minusDays(7);
}
System.out.println(dt);
Upvotes: 6
Reputation: 15683
Though I agree with scubabbl, here is a version without an inner while.
int year = 2008;
for (int m = Calendar.JANUARY; m <= Calendar.DECEMBER; m++) {
Calendar cal = new GregorianCalendar(year, m, 1);
cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
int diff = Calendar.FRIDAY - cal.get(Calendar.DAY_OF_WEEK);
if (diff > 0) {
diff -= 7;
}
cal.add(Calendar.DAY_OF_MONTH, diff);
System.out.println(cal.getTime());
}
Upvotes: 1
Reputation:
You never need to loop to find this out. For determining the "last Friday" date for this month, start with the first day of next month. Subtract the appropriate number of days depending on what (numerical) day of the week the first day of the month falls on. There's your "last Friday." I'm pretty sure it can be boiled down to a longish one-liner, but I'm not a java dev. So I'll leave that to someone else.
Upvotes: 9
Reputation: 12807
That looks like a perfectly acceptable solution. If that works, use it. That is minimal code and there's no reason to optimize it unless you have to.
Upvotes: 0