2008-09-16 18 views
14

estoy trabajando en un proyecto donde el requisito es tener una fecha calculada como siendo 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 se muestra lo probé por este año:últimos viernes de mes en Java

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

Respuesta

23

Basado en marked23's sugerencia:

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

Gran respuesta, pero ¿por qué utilizar el GregorianCalendar hormigón en lugar del Calendario abstracto devuelto por Calendar.getInstance()? –

+1

gran respuesta. parece ser el más corto y el más conciso. Me gustaría modificarlo de nuevo si pudiera. – Randyaa

+0

cal.get (Calendar.DAY_OF_WEEK)% 7 + 1; El% 7 + 1 es completamente innecesario aquí. cal.get (Calendar.DAY_OF_WEEK) devolverá un valor de 1 a 7 aquí ya (domingo es 1, sábado es 7).Modificar por 7 y luego agregar 1 literalmente no hace nada. –

1

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.

+0

Lo sentimos, ese código no es mínimo, bueno, ni siquiera correcto ... –

1

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

+0

¿A qué se refiere esto? –

+0

Se refiere a la cuestión –

1

Ligeramente más fácil de leer, el 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; 
} 
6

me gustaría utilizar 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 se puede tener una solución con (pero posiblemente no la más corta, pero sin duda más legible):

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

que nunca necesidad de bucle para averiguar 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.

1

Aunque estoy de acuerdo con scubabbl, aquí es una versión sin un tiempo 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()); 
} 
2

lo que necesita saber dos cosas - el número de días del mes, y el día de la semana del primer día del mes cae en.

Si el primer día del mes es un

  • domingo, entonces el último viernes es siempre 27.
  • lunes, entonces el último viernes es siempre el día 26.
  • Martes, entonces 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 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 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, a continuación, el último viernes es siempre el día 28.

sólo hay tres casos especiales.Una declaración solo interruptor y tres sentencias if (u operadores ternarios si se quiere que todos los casos tienen una sola línea ...)

trabajo en un papel. No se necesita ninguna bibliotecas especiales, funciones, conversiones, etc. Julian (bueno, excepto para obtener el día de la semana de la primera cae en, y tal vez el número de días de ese mes ...)

Aaron implemented it in Java.

-Adam

0

solución de ColinD no debería funcionar: prueba a ejecutarlo con diciembre de 2008 y que va a intentar establecer el mes 13 de un año. Sin embargo, reemplazar "cal.set (...)" por "cal.add (Calendar.MONTH, 1)" debería funcionar bien.

+1

En realidad, funciona bien con diciembre de 2008 y porque un calendario es indulgente por defecto. Y no puede simplemente reemplazar cal.set() por cal.add() porque entonces no estará en el primer día del mes. –

2

código para 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?"); 
}} 
+0

¡Impresionante! Gracias. –

0

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

Let Calendar.class haga su magia para usted;)

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

Esta es la mejor respuesta. Solo estaba buscando esto y todo lo que tenía que hacer era leer la documentación de DAY_OF_WEEK_IN_MONTH ... o esta respuesta. – Allen

+0

Funciona como un encanto, gracias. –

+0

El más simple y el mejor – Axel

1

aquí es cómo conseguir el último viernes, o lo que sea 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. 
0
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; 
} 
1

El siguiente programa 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 mes actual (fecha del sistema), desplazamiento = 1 significa mes siguiente, etc. El método 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<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 
    } 

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

java.time

Usando java.time biblioteca construida en Java 8 y versiones posteriores:

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 

Usted puede elegir cualquier día de la enumeración DayOfWeek: java.time.DayOfWeek.{MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, SUNDAY}.

Si es necesario agregar la información de tiempo, es posible utilizar cualquier LocalDate-LocalDateTime conversión disponibles como

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

Un mejor reemplazo para 'GregorianCalendar' sería [' ZonedDateTime'] (http://docs.oracle.com/javase/8/docs/api/java/time/ZonedDateTime.html) en lugar de 'LocalDateTime'. "Local" significa * any * localidad, sin zona horaria en particular, por lo que * no * representa un momento específico en la línea de tiempo. Por el contrario, un 'ZonedDateTime' es un momento específico en la línea de tiempo, con una zona horaria asignada ([' ZoneId'] (http://docs.oracle.com/javase/8/docs/api/java/time/ZoneId .html)). –

+0

Al llamar a 'LocalDate.now', sugiero que siempre pasen la zona horaria deseada/esperada, [' ZoneId'] (http://docs.oracle.com/javase/8/docs/api/java/time/ZoneId. html). Si se omite, la zona horaria predeterminada actual de la JVM se aplica de forma silenciosa. Ese valor predeterminado se puede cambiar en cualquier momento * durante el tiempo de ejecución * por cualquier código en cualquier aplicación en cualquier subproceso dentro de la JVM. Por lo tanto, no es prudente depender de tal valor. –

1

En Java 8, podemos hacerlo simplemente como:

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