gregorian java calendar

gregorian - Java Calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY), ¿se desplazará hacia atrás, hacia adelante o hacia un desconocido?



java calendar set time (8)

Supongamos que el siguiente código se ejecuta el 22 de agosto de 2009 (un sábado)

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

c.get(Calendar.DAY_OF_MONTH) devolverá 23. Me interesa que las condiciones regresen a las 14 (el último domingo, en lugar del próximo domingo).

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


Usando java.time

El enfoque moderno es con las clases de java.time que suplantan las antiguas y problemáticas clases de fecha y hora.

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

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

La enumeración del Month proporciona una docena de objetos predefinidos, uno para cada mes del año. Estos objetos de enumeración 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 numeración sana, 1-12 para enero-diciembre.

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

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

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

La enumeración 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 );

Fecha local: 2009-08-22 (sábado)

anterior domingo: 2009-08-16

siguiente domingo: 2009-08-23

Acerca de java.time

El marco java.time está integrado en Java 8 y java.time posteriores. Estas clases sustituyen a las antiguas y problemáticas clases de fecha y hora como java.util.Date , Calendar y SimpleDateFormat .

El proyecto Joda-Time , ahora en modo de mantenimiento , aconseja la migración a las clases java.time .

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

¿Dónde obtener las clases java.time?

  • Java SE 8 y SE 9 y posteriores
    • Incorporado.
    • Parte de la API de Java estándar con una implementación en paquete.
    • Java 9 agrega algunas características menores y correcciones.
  • Java SE 6 y SE 7
    • Gran parte de la funcionalidad de java.time está respaldada a Java 6 y 7 en ThreeTen-Backport .
  • Android
    • El proyecto ThreeTenABP adapta ThreeTen-Backport (mencionado anteriormente) para Android específicamente.
    • Vea Cómo usar ThreeTenABP… .

El proyecto ThreeTen-Extra extiende 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 .


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


Depende, en realidad. Considere el siguiente código de Java. En realidad es bastante simple y espero que se imprima el lunes anterior al 2011-09-18, que es el 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 en realidad 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 cambia realmente si WEEK_OF_YEAR !


Desde el Javadoc :

Si hay algún conflicto en los valores de los campos del calendario, Calendario da prioridad a los campos del calendario que se han establecido más recientemente. Las siguientes son las combinaciones predeterminadas de los campos del calendario. Se utilizará la combinación más reciente, según lo determinado por el campo único 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

Interpreto que esto significa que dado que está configurando el día de la semana, terminará combinándose con la semana del mes o la semana del año para producir la fecha y la hora reales.


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

(d + numberOfDaysInAWeek - firstDayOfWeek) % numberOfDaysInAWeek

o agrega 1 si quieres 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 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);


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


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 ). De la documentación:

Al configurar u obtener los campos WEEK_OF_MONTH o WEEK_OF_YEAR, el calendario debe determinar la primera semana del mes o año como punto de referencia. La primera semana de un mes o año se define como el período más temprano de siete días que comienza en los días getFirstDayOfWeek () y que contiene al menos getMinimalDaysInFirstWeek () días 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 de Calendario específica puede designar la semana anterior a la semana 1 de un año como la semana n del año anterior.


También debe comprobar cuál es el primer día de la 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.