2009-08-23 26 views
26

Supongamos el siguiente código es ejecutado el 22 de agosto de 2009 (sábado)Java Calendar.set (Calendar.DAY_OF_WEEK, Calendar.SUNDAY), ¿se desplazará hacia atrás, hacia adelante o será desconocido?

Calendar c = Calendar.getInstance(); 
    c.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); 

c.get(Calendar.DAY_OF_MONTH) volverá 23. Estoy interesado en las condiciones es devolvería 14 (último domingo, en lugar del próximo domingo)

¿Hay alguna regla asociada con la dirección en la que se desplegará el calendario DAY_OF_MONTH/YEAR cuando se establece DAY_OF_WEEK? ¿Si es así, Que son?

Respuesta

12

Siempre debe mantener el mismo WEEK_OF_MONTH (http://java.sun.com/j2se/1.4.2/docs/api/java/util/Calendar.html#WEEK_OF_MONTH). A partir de la documentación:

Al configurar u obtener los campos WEEK_OF_MONTH o WEEK_OF_YEAR , Calendario debe determinar la primera semana del mes o año como punto de referencia. La primera semana de un mes o años se define como el período más temprano de siete días a partir de getFirstDayOfWeek() y que contiene al getMinimalDaysInFirstWeek (días) menos de ese mes o año. Las semanas numeradas ..., -1, 0 preceden a la primera semana; semanas numeradas 2, 3, ... síguelo. Tenga en cuenta que la numeración normalizada devuelta por get() puede ser diferente. Por ejemplo, una subclase específica del calendario puede designar la semana anterior a semana 1 de un año como la semana n del año anterior .

1

Desde el Javadoc:

Si existe algún conflicto de valores de los campos de calendario, calendario da prioridad al calendario campos que se han establecido más recientemente. Las siguientes son las combinaciones predeterminadas de los campos del calendario. Se usará la combinación más reciente, según lo determinado por el campo individual establecido más recientemente.

Para los campos de fecha:

YEAR + MONTH + DAY_OF_MONTH 
YEAR + MONTH + WEEK_OF_MONTH + DAY_OF_WEEK 
YEAR + MONTH + DAY_OF_WEEK_IN_MONTH + DAY_OF_WEEK 
YEAR + DAY_OF_YEAR 
YEAR + DAY_OF_WEEK + WEEK_OF_YEAR 

que interpretan que esto significa que, dado que se está configurando día de la semana, que va a terminar siendo combinada con la semana de mes o semana del año con el fin para producir la fecha y hora actual.

7

la fórmula siguiente devuelve el día "actual" en una semana en la gama de [0; 6]

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek 

o añadir 1 si desea rango [1, 7]

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek + 1 

d es lo que Calendar.get(Calendar.DAY_OF_WEEK) devuelve

para obtener el primer día de la semana, reste el resultado de la fórmula a partir de la fecha actual.El siguiente código lo hace:

final int currentDayOfWeek = (calendar.get(Calendar.DAY_OF_WEEK) + 7 - cal.getFirstDayOfWeek()) % 7; 
cal.add(Calendar.DAY_OF_YEAR, -currentDayOfWeek); 
0

También debe comprobar cuál es el primer día de una semana. También pensé que siempre es domingo, pero esto depende de la configuración local, y en mi caso el lunes es el primer día de la semana. Establecer el domingo como primer día de la semana solucionó mi problema.

4

Depende, en realidad. Considere el siguiente código de Java. En realidad, es bastante simple y espero que para imprimir el lunes anterior 2011-09-18, es decir 2011-09-12:

Calendar calendar = Calendar.getInstance(Locale.GERMANY); 
System.out.printf("First day of week: %d%n%n", calendar.getFirstDayOfWeek()); 

calendar.set(2011, Calendar.SEPTEMBER, 18); 
System.out.printf("Starting day: %tF%n", calendar); 
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); 
System.out.printf("Last monday: %tF%n%n", calendar); 

calendar.set(2011, Calendar.SEPTEMBER, 18); 
System.out.printf("Starting day: %tF (week %d)%n", 
     calendar, calendar.get(Calendar.WEEK_OF_YEAR)); 
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); 
System.out.printf("Last monday: %tF (week %d)%n", calendar, 
     calendar.get(Calendar.WEEK_OF_YEAR)); 

Pero, de hecho, el resultado es un poco diferente:

First day of week: 2 

Starting day: 2011-09-18 
Last monday: 2011-09-19 

Starting day: 2011-09-18 (week 37) 
Last monday: 2011-09-12 (week 37) 

En otras palabras, el resultado depende de si mi calendario sabe que podría estar interesado en la semana. ¡El resultado realmente cambia si consulto WEEK_OF_YEAR!

0

depende del primer día de la semana:

/** 
* Gets what the first day of the week is; e.g., <code>SUNDAY</code> in the U.S., 
* <code>MONDAY</code> in France. 
* 
* @return the first day of the week. 
* @see #setFirstDayOfWeek(int) 
* @see #getMinimalDaysInFirstWeek() 
*/ 
public int getFirstDayOfWeek() 
{ 
    return firstDayOfWeek; 
} 
0

Se puede utilizar como este método.

public Integer whichDayOfWeek(Calendar calendar) { 
      if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY) { 
       return 1; 
      } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.TUESDAY) { 
       return 2; 
      } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.WEDNESDAY) { 
       return 3; 
      } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.THURSDAY) { 
       return 4; 
      } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.FRIDAY) { 
       return 5; 
      } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY) { 
       return 6; 
      } else if (calendar.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) { 
       return 7; 
      } else { 
       return null; 
      } 
     } 
0

Usando java.time

El enfoque moderno es con las clases java.time que suplantan los legados de edad clases de fecha y hora problemáticos.

Las clases de java.time son mucho más fáciles de usar. En particular, eliminan la ambigüedad planteada en la Pregunta. Puede solicitar explícitamente el anterior el domingo o el posterior el domingo.

La clase LocalDate representa un valor de fecha solamente sin hora del día y sin zona horaria.

Enum proporciona una docena de objetos predefinidos, uno para cada mes del año. Estos objetos enumerados son más seguros de usar, pero en su lugar puede usar un número simple para el mes. A diferencia de las clases heredadas, estos meses tienen una buena cantidad, 1-12 para enero-diciembre.

LocalDate localDate = LocalDate.of(2009 , Month.AUGUST, 22); 

La interfaz TemporalAdjuster proporciona para la manipulación de los valores de fecha y hora. La clase TemporalAdjusters (tenga en cuenta el plural s) proporciona varias implementaciones útiles.

previous & next ajustadores excluyen la fecha de la consideración. Los métodos previousOrSame & nextOrSame devuelven la fecha en cuestión si es el día de la semana deseado.

Enum DayOfWeek proporciona siete objetos predefinidos, uno para cada día de la semana.

LocalDate previousSunday = localDate.with(TemporalAdjusters.previous (DayOfWeek.SUNDAY)); 
LocalDate previousOrSameSunday = localDate.with(TemporalAdjusters.previousOrSame (DayOfWeek.SUNDAY)); 

LocalDate nextSunday = localDate.with(TemporalAdjusters.next (DayOfWeek.SUNDAY)); 
LocalDate nextOrSameSunday = localDate.with(TemporalAdjusters.nextOrSame (DayOfWeek.SUNDAY)); 

Volcar a la consola.

System.out.println ("localDate: " + localDate + " (" + localDate.getDayOfWeek().getDisplayName (TextStyle.FULL, Locale.US) + ")"); 
System.out.println ("previousSunday: " + previousSunday); 
System.out.println ("nextSunday: " + nextSunday); 

LocalDate: 2009-08-22 (sábado)

previousSunday: 2009-08-16

nextSunday: 2009-08-23


Acerca de java.time

El marco java.time está integrado en Java 8 y posterior. Estas clases suplantan a las viejas y problemáticas clases de fecha y hora legacy, como java.util.Date, Calendar, & SimpleDateFormat.

El proyecto Joda-Time, ahora en maintenance mode, recomienda la migración a las clases java.time.

Para obtener más información, consulte el Oracle Tutorial. Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310.

¿Dónde obtener las clases java.time?

  • Java SE 8 y SE 9 y más tarde
    • incorporado.
    • Parte de la API estándar de Java con una implementación integrada.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y SE 7
    • Gran parte de la funcionalidad de back-java.time está portado a Java 6 & 7 en ThreeTen-Backport.
  • Android

El proyecto se extiende ThreeTen-Extra java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuarter y more.

Cuestiones relacionadas