Clase Calendar de Java

La clase Calendar es una clase abstracta en Java para manejar fechas y horas, que se encuentra en eljava.utilpaquete. Esta clase proporciona una serie de métodos para operar con campos de fecha y hora (como año, mes, día, hora, minuto, etc.), y puede realizar cálculos y comparaciones de fechas.

¿Por qué se necesita la clase Calendar?

En Java, aunque la clase Date también puede representar fechas y horas, tiene las siguientes limitaciones:

  1. La mayoría de sus métodos están obsoletos (deprecated)
  2. No admite internacionalización
  3. Funcionalidad limitada para el cálculo de fechas

La clase Calendar resuelve estos problemas y proporciona funciones de operación de fecha y hora más potentes y flexibles.


Uso básico de la clase Calendar

Obtener una instancia de Calendar

Debido a que Calendar es una clase abstracta, no podemos instanciarla directamente. El método estándar para obtener una instancia de Calendar es:

Ejemplo

Calendar calendar = Calendar.getInstance();

Este método devuelve una instancia de Calendar (normalmente GregorianCalendar) según la zona horaria y la región predeterminadas.

Establecer fecha y hora

Podemos utilizar elset()método para establecer los distintos campos del objeto Calendar:

Ejemplo

// Establecer año, mes y día
calendar.set(2023, Calendar.NOVEMBER, 15);

// Establecer año, mes, día, hora, minuto y segundo
calendar.set(2023, Calendar.NOVEMBER, 15, 14, 30, 0);

Nota: los meses comienzan desde 0; 0 representa enero y 11 representa diciembre. Para evitar confusiones, se recomienda usar las constantes definidas en la clase Calendar (como Calendar.JANUARY, Calendar.FEBRUARY, etc.).

Obtener información de fecha y hora

Usando elget()método se pueden obtener los distintos campos del objeto Calendar:

Ejemplo

int year = calendar.get(Calendar.YEAR);       // Obtener el año
int month = calendar.get(Calendar.MONTH);     // Obtener el mes (0-11)
int day = calendar.get(Calendar.DAY_OF_MONTH);// Obtener el día
int hour = calendar.get(Calendar.HOUR_OF_DAY);// Obtener la hora (formato de 24 horas)
int minute = calendar.get(Calendar.MINUTE);   // Obtener los minutos
int second = calendar.get(Calendar.SECOND);   // Obtener los segundos

Métodos comunes de la clase Calendar

Cálculo de fechas

La clase Calendar proporciona métodos convenientes para el cálculo de fechas:

Ejemplo

// Añadir 10 días a la fecha actual
calendar.add(Calendar.DAY_OF_MONTH, 10);

// Restar 3 meses al mes actual
calendar.add(Calendar.MONTH, -3);

Comparación de fechas

Podemos utilizar elcompareTo()método para comparar dos objetos Calendar:

Ejemplo

Calendar cal1 = Calendar.getInstance();
Calendar cal2 = Calendar.getInstance();
cal2.add(Calendar.DAY_OF_MONTH, 1);

int result = cal1.compareTo(cal2);
// result < 0 indica que cal1 es anterior a cal2
// result == 0 indica que cal1 es igual a cal2
// result > 0 indica que cal1 es posterior a cal2

Obtener la marca de tiempo (timestamp)

Se puede utilizar elgetTimeInMillis()método para obtener la marca de tiempo (en milisegundos) representada por el objeto Calendar:

Ejemplo

long timestamp = calendar.getTimeInMillis();

También se puede utilizar elgetTime()método para convertirlo en un objeto Date:

Ejemplo

Date date = calendar.getTime();

Usos avanzados de la clase Calendar

Establecer zona horaria

Podemos establecer una zona horaria específica para el objeto Calendar:

Ejemplo

TimeZone timeZone = TimeZone.getTimeZone("America/New_York");
calendar.setTimeZone(timeZone);

Operaciones con campos del calendario

La clase Calendar proporciona elroll()método, que permite desplazar un campo sin afectar a otros campos:

Ejemplo

// Incrementar el mes en 1, pero no cambiará el año
calendar.roll(Calendar.MONTH, true);  // o calendar.roll(Calendar.MONTH, 1);

Obtener el primer día de la semana

La definición del primer día de la semana varía según la región (en algunos lugares es domingo, en otros es lunes):

Ejemplo

int firstDayOfWeek = calendar.getFirstDayOfWeek();

Ejemplo completo

Ejemplo

import java.util.Calendar;
import java.util.GregorianCalendar;
import java.text.SimpleDateFormat;

public class CalendarDemo {
    public static void main(String[] args) {
        // 1. Obtener una instancia de Calendar (por defecto usa la fecha y hora actuales)
        Calendar calendar = Calendar.getInstance();
       
        // 2. Obtener los valores de cada campo
        int year = calendar.get(Calendar.YEAR);
        int month = calendar.get(Calendar.MONTH) + 1; // El mes comienza desde 0, hay que sumar 1
        int day = calendar.get(Calendar.DAY_OF_MONTH);
        int hour = calendar.get(Calendar.HOUR_OF_DAY); // Formato de 24 horas
        int minute = calendar.get(Calendar.MINUTE);
        int second = calendar.get(Calendar.SECOND);
       
        System.out.printf("Hora actual: %d año %d mes %d día %d:%d:%d%n",
                        year, month, day, hour, minute, second);
       
        // 3. Establecer una fecha y hora específicas
        calendar.set(2023, Calendar.MAY, 15, 10, 30, 0); // 15 de mayo de 2023, 10:30:00
       
        // 4. Usar SimpleDateFormat para formatear la salida
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        System.out.println("Hora establecida: " + sdf.format(calendar.getTime()));
       
        // 5. Operaciones con fechas
        calendar.add(Calendar.DAY_OF_MONTH, 5); // Añadir 5 días
        calendar.add(Calendar.HOUR, -3); // Restar 3 horas
       
        System.out.println("Hora después de la operación: " + sdf.format(calendar.getTime()));
       
        // 6. Comparar fechas
        Calendar anotherCalendar = new GregorianCalendar(2023, Calendar.JUNE, 1);
        System.out.println("Resultado de la comparación: " +
            (calendar.before(anotherCalendar) ? "antes" : "después"));
       
        // 7. Obtener el día de la semana (domingo=1, sábado=7)
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        System.out.println("Día de la semana " + getChineseWeekday(dayOfWeek));
    }
   
    private static String getChineseWeekday(int dayOfWeek) {
        String[] weekdays = {"", "domingo", "lunes", "martes", "miércoles", "jueves", "viernes", "sábado"};
        return weekdays[dayOfWeek];
    }
}

Resultado de salida:

当前时间: 2023年5月15日 14:25:36
设置后的时间: 2023-05-15 10:30:00
运算后的时间: 2023-05-20 07:30:00
比较结果: 之前
星期二

Consideraciones sobre la clase Calendar

  1. El mes comienza desde 0: En la clase Calendar, los meses comienzan desde 0 (0=enero, 11=diciembre), lo que puede dar lugar a errores.

  2. Mutabilidad: Los objetos Calendar son mutables; modificar un objeto Calendar afecta a todos los lugares que lo referencian.

  3. Seguridad para hilos (thread safety): La clase Calendar no es segura para hilos; en entornos multihilo se necesita sincronización adicional.

  4. Rendimiento: Crear instancias de Calendar con frecuencia afecta al rendimiento; se puede considerar reutilizar instancias.

  5. Problemas de zona horaria: Por defecto se usa la zona horaria del sistema; en aplicaciones que cruzan zonas horarias se debe prestar especial atención.


Alternativas en Java 8

Desde Java 8, se introdujo la nueva API de fecha y hora (java.timepaquete), que proporciona una forma más moderna y fácil de manejar fechas y horas. Si se usa Java 8 o una versión superior, se recomienda usar la nueva API:

Ejemplo

// Nueva API que reemplaza a Calendar
LocalDate date = LocalDate.now();
LocalDateTime dateTime = LocalDateTime.now();
ZonedDateTime zonedDateTime = ZonedDateTime.now();

La nueva API resuelve muchos problemas de la clase Calendar, incluyendo una mejor seguridad para hilos, un diseño de API más intuitivo y funciones más potentes.


Métodos comunes de la clase Calendar de Java

A continuación se presentan los métodos comunes de la clase java.util.Calendar:

Métodos básicos

Método Descripción Ejemplo
static Calendar getInstance() Obtener una instancia de Calendar con la zona horaria y la configuración regional predeterminadas Calendar cal = Calendar.getInstance()
static Calendar getInstance(TimeZone zone) Obtener una instancia de Calendar con una zona horaria específica Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"))
static Calendar getInstance(Locale locale) Obtener una instancia de Calendar con una configuración regional específica Calendar cal = Calendar.getInstance(Locale.CHINA)
static Calendar getInstance(TimeZone zone, Locale locale) Obtener una instancia de Calendar con una zona horaria y configuración regional específicas Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT+8"), Locale.CHINA)

Constantes de campo (comunes)

Campo Descripción Rango de valores
Calendar.YEAR Campo del año -
Calendar.MONTH Campo del mes 0-11 (0 representa enero)
Calendar.DATEoCalendar.DAY_OF_MONTH Día del mes 1-31
Calendar.DAY_OF_WEEK Día de la semana 1-7 (1 representa domingo)
Calendar.HOUR Hora en formato de 12 horas 0-11
Calendar.HOUR_OF_DAY Hora en formato de 24 horas 0-23
Calendar.MINUTE Minutos 0-59
Calendar.SECOND segundo 0-59
Calendar.MILLISECOND Milisegundos 0-999
Calendar.AM_PM AM o PM (mañana o tarde) 0 (AM) o 1 (PM)

Métodos de operación de fecha y hora

Método Descripción Ejemplo
int get(int field) Obtener el valor del campo especificado int year = cal.get(Calendar.YEAR)
void set(int field, int value) Establecer el valor del campo especificado cal.set(Calendar.MONTH, 5)(Establecer a junio)
void set(int year, int month, int date) Establecer año, mes, día cal.set(2023, 5, 15)(15 de junio de 2023)
void set(int year, int month, int date, int hourOfDay, int minute) Establecer año, mes, día, hora, minuto cal.set(2023, 5, 15, 14, 30)
void set(int year, int month, int date, int hourOfDay, int minute, int second) Establecer año, mes, día, hora, minuto, segundo cal.set(2023, 5, 15, 14, 30, 45)
void add(int field, int amount) Añadir o restar la cantidad de tiempo especificada cal.add(Calendar.DATE, 5)(Añadir 5 días)
void roll(int field, int amount) Añadir o restar una cantidad de tiempo sin cambiar campos mayores cal.roll(Calendar.DATE, 5)(Solo cambia el campo de día)

Métodos de comparación de tiempo

Método Descripción Ejemplo
boolean after(Object when) Determina si este Calendar está después del tiempo especificado cal1.after(cal2)
boolean before(Object when) Determina si este Calendar está antes del tiempo especificado cal1.before(cal2)
int compareTo(Calendar anotherCalendar) Compara el orden temporal de dos objetos Calendar cal1.compareTo(cal2)

Otros métodos útiles

Método Descripción Ejemplo
long getTimeInMillis() Devuelve el valor de tiempo de este Calendar (milisegundos) long millis = cal.getTimeInMillis()
void setTimeInMillis(long millis) Establece el Calendar con el valor de tiempo en milisegundos dado cal.setTimeInMillis(1626345600000L)
Date getTime() Devuelve un objeto Date que representa el valor de tiempo de este Calendar Date date = cal.getTime()
void setTime(Date date) Establece el tiempo del Calendar usando el Date dado cal.setTime(new Date())
void clear() Borrar todos los valores de campo cal.clear()
void clear(int field) Borrar el valor del campo especificado cal.clear(Calendar.HOUR)
boolean isSet(int field) Determina si el campo especificado tiene un valor establecido if(cal.isSet(Calendar.YEAR))
Otras extensiones