Obtenga el último viernes del mes en Java

Estoy trabajando en un proyecto donde el requisito es tener una fecha calculada como el último viernes de un mes determinado. Creo que tengo una solución que solo usa Java estándar, pero me preguntaba si alguien sabía algo más conciso o eficiente. A continuación está lo que probé para este año:

for (int month = 0; 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()); } 

Basado en la sugerencia de marked23 :

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

Deje que Calendar.class haga su magia para usted;)

 pCal.set(GregorianCalendar.DAY_OF_WEEK,Calendar.FRIDAY); pCal.set(GregorianCalendar.DAY_OF_WEEK_IN_MONTH, -1); 

Nunca necesita hacer un bucle para descubrir esto. Para determinar la fecha del “último viernes” para este mes, comience con el primer día del próximo mes. Reste el número apropiado de días dependiendo de qué día (numérico) de la semana caiga el primer día del mes. Está tu “último viernes”. Estoy bastante seguro de que se puede resumir en una versión un poco larga, pero no soy un desarrollador de Java. Así que lo dejo a otra persona.

Usaría una biblioteca como Jodatime . Tiene una API muy útil y usa números de mes normales. Y lo mejor de todo, es seguro para subprocesos.

Creo que puedes tener una solución con (pero posiblemente no la más corta, pero ciertamente más fácil de leer):

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

java.time

Usando la biblioteca java.time incorporada en Java 8 y posterior:

 import java.time.{DayOfWeek, LocalDate} import java.time.temporal.TemporalAdjusters.lastInMonth val now = LocalDate.now() # 2015-11-23 val lastInMonth = now.`with`(lastInMonth(DayOfWeek.FRIDAY)) # 2015-11-27 

Puede elegir cualquier día del DayOfWeek : java.time.DayOfWeek.{MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY} .

Si necesita agregar información de tiempo, puede usar cualquier LocalDate disponible de LocalDate a LocalDateTime como

 lastFriday.atStartOfDay() # 2015-11-27T00:00 

Necesita saber dos cosas: el número de días del mes y el día de la semana el primero del mes.

Si el primer día del mes es un

  • Domingo, luego el último viernes es siempre el día 27.
  • Lunes, luego el último viernes es siempre el día 26.
  • Martes, luego el último viernes es siempre el día 25.
  • Miércoles, luego el último viernes es el día 24, a menos que haya 31 días en el mes, entonces es el día 31
  • Jueves, luego el último viernes es el día 23, a menos que haya 30 días o más en el mes, entonces es el día 30.
  • Viernes, luego el último viernes es el día 22, a menos que haya 29 días o más en el mes, entonces es el día 29.
  • Sábado, luego el último viernes es siempre el día 28.

Solo hay tres casos especiales. Una única statement de conmutación y tres declaraciones if (o operadores ternarios si desea que cada caso tenga una sola línea …)

Resuélvelo en papel. No necesita ninguna biblioteca especial, funciones, conversiones julianas, etc. (bueno, excepto para que el día de la semana caiga el primero, y tal vez el número de días de ese mes …)

Aaron lo implementó en Java.

-Adán

código para el algoritmo de Adam Davis

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

Eso parece una solución perfectamente aceptable. Si eso funciona, úsalo. Ese es un código mínimo y no hay razón para optimizarlo a menos que sea necesario.

Eso no funcionará Su ciclo va a repetirse 13 veces (0 a 12).

Aunque estoy de acuerdo con scubabbl, aquí hay una versión sin un momento interno.

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

Ligeramente más fácil de leer, enfoque de fuerza bruta:

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

Así es cómo obtener el último viernes o el día de la semana del mes:

 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. 

El siguiente progtwig es para el último viernes de cada mes. se puede usar para obtener el último día de la semana en cualquier mes. La variable offset=0 significa el mes actual (fecha del sistema), offset = 1 significa el mes siguiente, etc. El getLastFridayofMonth(int offset) devolverá el último viernes.

 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 

En Java 8, podemos hacerlo simplemente como:

 LocalDate lastFridayOfMonth = LocalDate .now() .with(lastDayOfMonth()) .with(previous(DayOfWeek.FRIDAY)); 

Hay una serie de métodos útiles para calcular el día de la semana . Con un poco de álgebra agregada, una de ellas debe ser adaptable a su problema.

La solución de ColinD no debería funcionar: intente ejecutarla en diciembre de 2008 y tratará de establecer el decimotercer mes de un año. Sin embargo, reemplazar “cal.set (…)” por “cal.add (Calendar.MONTH, 1)” debería funcionar bien.

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

Espero que esto ayude..

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