Clase Java ZonedDateTime
ZonedDateTime es una clase importante en la API de fecha y hora introducida en Java 8 (paquete java.time). Representa una fecha y hora con zona horaria. Esta clase combina LocalDateTime y ZoneId, y puede representar con precisión un punto en el tiempo en una zona horaria específica.
Características principales
- Incluye fecha (año, mes, día)
- Incluye hora (hora, minuto, segundo, nanosegundo)
- Incluye información de zona horaria
- Es una clase inmutable y segura para subprocesos
- Admite conversión de zona horaria y ajuste automático del horario de verano
Formas de crear ZonedDateTime
1. Crear con la hora actual
Ejemplo
// Obtener la fecha y hora de la zona horaria predeterminada del sistema
ZonedDateTime now = ZonedDateTime.now();
// Obtener la fecha y hora actual de la zona horaria especificada
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
ZonedDateTime now = ZonedDateTime.now();
// Obtener la fecha y hora actual de la zona horaria especificada
ZonedDateTime nowInTokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
2. Crear a partir de componentes
Ejemplo
// Especificar año, mes, día, hora, minuto, segundo y zona horaria
ZonedDateTime customDateTime = ZonedDateTime.of(
2023, 12, 25, 15, 30, 0, 0,
ZoneId.of("America/New_York")
);
ZonedDateTime customDateTime = ZonedDateTime.of(
2023, 12, 25, 15, 30, 0, 0,
ZoneId.of("America/New_York")
);
3. Combinar LocalDateTime y ZoneId
Ejemplo
LocalDateTime localDateTime = LocalDateTime.of(2023, 6, 15, 10, 30);
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime parisTime = ZonedDateTime.of(localDateTime, zoneId);
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime parisTime = ZonedDateTime.of(localDateTime, zoneId);
Métodos de operación comunes
1. Obtener información de fecha y hora
Ejemplo
ZonedDateTime zdt = ZonedDateTime.now();
int year = zdt.getYear(); // año
Month month = zdt.getMonth(); // mes
int day = zdt.getDayOfMonth(); // día
int hour = zdt.getHour(); // hora
int minute = zdt.getMinute(); // minuto
int second = zdt.getSecond(); // segundo
ZoneId zone = zdt.getZone(); // zona horaria
int year = zdt.getYear(); // año
Month month = zdt.getMonth(); // mes
int day = zdt.getDayOfMonth(); // día
int hour = zdt.getHour(); // hora
int minute = zdt.getMinute(); // minuto
int second = zdt.getSecond(); // segundo
ZoneId zone = zdt.getZone(); // zona horaria
2. Operaciones de suma y resta de tiempo
Ejemplo
ZonedDateTime zdt = ZonedDateTime.now();
// sumar 1 día
ZonedDateTime tomorrow = zdt.plusDays(1);
// restar 2 horas
ZonedDateTime twoHoursEarlier = zdt.minusHours(2);
// sumar 3 semanas
ZonedDateTime threeWeeksLater = zdt.plusWeeks(3);
// sumar 1 día
ZonedDateTime tomorrow = zdt.plusDays(1);
// restar 2 horas
ZonedDateTime twoHoursEarlier = zdt.minusHours(2);
// sumar 3 semanas
ZonedDateTime threeWeeksLater = zdt.plusWeeks(3);
3. Conversión de zona horaria
Ejemplo
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
// Convertir a hora de Nueva York
ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// Convertir a hora UTC
ZonedDateTime utcTime = tokyoTime.withZoneSameInstant(ZoneOffset.UTC);
// Convertir a hora de Nueva York
ZonedDateTime newYorkTime = tokyoTime.withZoneSameInstant(ZoneId.of("America/New_York"));
// Convertir a hora UTC
ZonedDateTime utcTime = tokyoTime.withZoneSameInstant(ZoneOffset.UTC);
Ejemplos de aplicaciones prácticas
1. Calcular la diferencia horaria entre dos zonas horarias
Ejemplo
ZonedDateTime londonTime = ZonedDateTime.now(ZoneId.of("Europe/London"));
ZonedDateTime sydneyTime = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
// Calcular la diferencia en horas
long hoursBetween = ChronoUnit.HOURS.between(londonTime, sydneyTime);
System.out.println("Diferencia horaria actual entre Londres y Sídney: " + hoursBetween + "horas");
ZonedDateTime sydneyTime = ZonedDateTime.now(ZoneId.of("Australia/Sydney"));
// Calcular la diferencia en horas
long hoursBetween = ChronoUnit.HOURS.between(londonTime, sydneyTime);
System.out.println("Diferencia horaria actual entre Londres y Sídney: " + hoursBetween + "horas");
2. Manejar horarios de reuniones entre zonas horarias
Ejemplo
// La reunión en Nueva York es a las 3 p.m.
ZonedDateTime meetingTimeNY = ZonedDateTime.of(
LocalDate.now(),
LocalTime.of(15, 0),
ZoneId.of("America/New_York")
);
// Convertir a hora de Tokio
ZonedDateTime meetingTimeTokyo = meetingTimeNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println("Los asistentes en Tokio deben estar a la hora local: " + meetingTimeTokyo);
ZonedDateTime meetingTimeNY = ZonedDateTime.of(
LocalDate.now(),
LocalTime.of(15, 0),
ZoneId.of("America/New_York")
);
// Convertir a hora de Tokio
ZonedDateTime meetingTimeTokyo = meetingTimeNY.withZoneSameInstant(ZoneId.of("Asia/Tokyo"));
System.out.println("Los asistentes en Tokio deben estar a la hora local: " + meetingTimeTokyo);
3. Manejo del horario de verano
Ejemplo
// Hora en Nueva York antes y después del cambio de horario de verano
ZonedDateTime beforeDST = ZonedDateTime.of(
LocalDateTime.of(2023, 3, 11, 1, 30),
ZoneId.of("America/New_York")
);
ZonedDateTime afterDST = beforeDST.plusHours(1);
System.out.println("Diferencia horaria real: " +
Duration.between(beforeDST, afterDST).toHours() + "horas");
ZonedDateTime beforeDST = ZonedDateTime.of(
LocalDateTime.of(2023, 3, 11, 1, 30),
ZoneId.of("America/New_York")
);
ZonedDateTime afterDST = beforeDST.plusHours(1);
System.out.println("Diferencia horaria real: " +
Duration.between(beforeDST, afterDST).toHours() + "horas");
Conversión de ZonedDateTime con otras clases de fecha y hora
1. Convertir a Instant
Ejemplo
ZonedDateTime zdt = ZonedDateTime.now();
Instant instant = zdt.toInstant(); // Convertir a marca de tiempo UTC
Instant instant = zdt.toInstant(); // Convertir a marca de tiempo UTC
2. Convertir a LocalDateTime
Ejemplo
ZonedDateTime zdt = ZonedDateTime.now();
LocalDateTime ldt = zdt.toLocalDateTime(); // Se pierde la información de zona horaria
LocalDateTime ldt = zdt.toLocalDateTime(); // Se pierde la información de zona horaria
3. Crear desde Instant
Ejemplo
Instant instant = Instant.now();
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));
ZonedDateTime zdt = instant.atZone(ZoneId.of("Asia/Shanghai"));
Ejemplo integral
Ejemplo
import java.time.ZonedDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class ZonedDateTimeDemo {
public static void main(String[] args) {
// 1. Obtener la hora actual de la zona horaria actual
ZonedDateTime now = ZonedDateTime.now();
System.out.println("Hora de la zona horaria actual: " + now);
// 2. Obtener la hora actual de una zona horaria específica
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("Hora de Tokio: " + tokyoTime);
// 3. Crear una fecha y hora específica con zona horaria
ZonedDateTime specificTime = ZonedDateTime.of(
2023, 5, 15, 10, 30, 0, 0,
ZoneId.of("America/New_York")
);
System.out.println("Hora específica en Nueva York: " + specificTime);
// 4. Conversión de zona horaria
ZonedDateTime londonTime = specificTime.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println("Hora correspondiente en Londres: " + londonTime);
// 5. Salida formateada
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println("Hora formateada: " + now.format(formatter));
// 6. Obtener información de cada parte
System.out.println("Zona horaria: " + now.getZone());
System.out.println("Año: " + now.getYear());
System.out.println("Mes: " + now.getMonth());
System.out.println("Hora: " + now.getHour());
}
}
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
public class ZonedDateTimeDemo {
public static void main(String[] args) {
// 1. Obtener la hora actual de la zona horaria actual
ZonedDateTime now = ZonedDateTime.now();
System.out.println("Hora de la zona horaria actual: " + now);
// 2. Obtener la hora actual de una zona horaria específica
ZonedDateTime tokyoTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
System.out.println("Hora de Tokio: " + tokyoTime);
// 3. Crear una fecha y hora específica con zona horaria
ZonedDateTime specificTime = ZonedDateTime.of(
2023, 5, 15, 10, 30, 0, 0,
ZoneId.of("America/New_York")
);
System.out.println("Hora específica en Nueva York: " + specificTime);
// 4. Conversión de zona horaria
ZonedDateTime londonTime = specificTime.withZoneSameInstant(ZoneId.of("Europe/London"));
System.out.println("Hora correspondiente en Londres: " + londonTime);
// 5. Salida formateada
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
System.out.println("Hora formateada: " + now.format(formatter));
// 6. Obtener información de cada parte
System.out.println("Zona horaria: " + now.getZone());
System.out.println("Año: " + now.getYear());
System.out.println("Mes: " + now.getMonth());
System.out.println("Hora: " + now.getHour());
}
}
La salida es similar a lo siguiente:
当前时区时间: 2025-05-01T11:29:07.411467+08:00[Asia/Shanghai] 东京时间: 2025-05-01T12:29:07.417938+09:00[Asia/Tokyo] 纽约特定时间: 2023-05-15T10:30-04:00[America/New_York] 对应的伦敦时间: 2023-05-15T15:30+01:00[Europe/London] 格式化时间: 2025-05-01 11:29:07 CST 时区: Asia/Shanghai 年份: 2025 月份: MAY 小时: 11
Mejores prácticas
- Almacenamiento y transmisión: al almacenar en bases de datos o transmitir por red, se recomienda usar Instant o ZonedDateTime en hora UTC
- Visualización: convierta a la zona horaria local solo al mostrar en la interfaz de usuario
- Comparación: al comparar horas de diferentes zonas horarias, convierta primero a la misma zona horaria o a Instant
- Horario de verano: use siempre el ID de zona horaria completo (como "America/New_York") en lugar de un simple desplazamiento (como "-05:00")
ZonedDateTime es una herramienta poderosa para manejar aplicaciones sensibles a la zona horaria; usarlo correctamente puede evitar muchos problemas comunes de fecha y hora.
Métodos de fábrica estáticos
| Método | Descripción | Ejemplo |
|---|---|---|
static ZonedDateTime now() |
Obtener la fecha y hora actual de la zona horaria actual | ZonedDateTime.now() |
static ZonedDateTime now(ZoneId zone) |
Obtener la fecha y hora actual de la zona horaria especificada | ZonedDateTime.now(ZoneId.of("Asia/Shanghai")) |
static ZonedDateTime of(int year, int month, int day, int hour, int minute, int second, int nano, ZoneId zone) |
Crear especificando parámetros | ZonedDateTime.of(2023, 6, 15, 14, 30, 0, 0, ZoneId.of("GMT+8")) |
static ZonedDateTime of(LocalDate date, LocalTime time, ZoneId zone) |
Crear combinando LocalDate, LocalTime y zona horaria | ZonedDateTime.of(LocalDate.now(), LocalTime.now(), ZoneId.systemDefault()) |
static ZonedDateTime of(LocalDateTime localDateTime, ZoneId zone) |
Crear desde LocalDateTime y zona horaria | ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("America/New_York")) |
static ZonedDateTime ofInstant(Instant instant, ZoneId zone) |
Crear desde Instant y zona horaria | ZonedDateTime.ofInstant(Instant.now(), ZoneId.of("UTC")) |
static ZonedDateTime parse(CharSequence text) |
Analizar desde una cadena | ZonedDateTime.parse("2023-06-15T14:30:45+08:00[Asia/Shanghai]") |
static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) |
Analizar usando un formato específico | ZonedDateTime.parse("2023-06-15 14:30 CST", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm z")) |
Obtener información de fecha y hora
| Método | Descripción | Ejemplo |
|---|---|---|
int getYear() |
Obtener el año | 2023 |
Month getMonth() |
Obtener el mes (enum Month) | Month.JUNE |
int getMonthValue() |
Obtener el valor del mes (1-12) | 6 |
int getDayOfMonth() |
Obtener el día del mes | 15 |
int getDayOfYear() |
Obtener el día del año | 166 |
DayOfWeek getDayOfWeek() |
Obtener el día de la semana (enum DayOfWeek) | DayOfWeek.THURSDAY |
int getHour() |
Obtener la hora (0-23) | 14 |
int getMinute() |
Obtener el minuto (0-59) | 30 |
int getSecond() |
Obtener el segundo (0-59) | 45 |
int getNano() |
Obtener el nanosegundo | 0 |
ZoneId getZone() |
Obtener la zona horaria | Asia/Shanghai |
ZoneOffset getOffset() |
Obtener el desplazamiento de zona horaria | +08:00 |
Operaciones de fecha y hora
| Método | Descripción | Ejemplo |
|---|---|---|
ZonedDateTime plusDays(long days) |
Agregar días | zdt.plusDays(5) |
ZonedDateTime plusHours(long hours) |
Agregar horas | zdt.plusHours(2) |
ZonedDateTime plusMinutes(long minutes) |
Agregar minutos | zdt.plusMinutes(30) |
ZonedDateTime plusSeconds(long seconds) |
Agregar segundos | zdt.plusSeconds(45) |
ZonedDateTime plusNanos(long nanos) |
Agregar nanosegundos | zdt.plusNanos(1000000) |
ZonedDateTime minusDays(long days) |
Restar días | zdt.minusDays(5) |
ZonedDateTime minusHours(long hours) |
Restar horas | zdt.minusHours(2) |
ZonedDateTime minusMinutes(long minutes) |
Restar minutos | zdt.minusMinutes(30) |
ZonedDateTime minusSeconds(long seconds) |
Restar segundos | zdt.minusSeconds(45) |
ZonedDateTime minusNanos(long nanos) |
Restar nanosegundos | zdt.minusNanos(1000000) |
ZonedDateTime withYear(int year) |
Modificar el año | zdt.withYear(2024) |
ZonedDateTime withMonth(int month) |
Modificar el mes | zdt.withMonth(12) |
ZonedDateTime withDayOfMonth(int day) |
Modificar el día del mes | zdt.withDayOfMonth(1) |
ZonedDateTime withHour(int hour) |
Modificar la hora | zdt.withHour(0) |
ZonedDateTime withMinute(int minute) |
Modificar el minuto | zdt.withMinute(0) |
ZonedDateTime withSecond(int second) |
Modificar el segundo | zdt.withSecond(0) |
ZonedDateTime withNano(int nano) |
Modificar el nanosegundo | zdt.withNano(0) |
ZonedDateTime withZoneSameInstant(ZoneId zone) |
Convertir zona horaria (manteniendo el mismo instante) | zdt.withZoneSameInstant(ZoneId.of("UTC")) |
ZonedDateTime withZoneSameLocal(ZoneId zone) |
Convertir zona horaria (manteniendo la hora local) | zdt.withZoneSameLocal(ZoneId.of("UTC")) |
Métodos de conversión
| Método | Descripción | Ejemplo |
|---|---|---|
LocalDate toLocalDate() |
Convertir a LocalDate | zdt.toLocalDate() |
LocalTime toLocalTime() |
Convertir a LocalTime | zdt.toLocalTime() |
LocalDateTime toLocalDateTime() |
Convertir a LocalDateTime | zdt.toLocalDateTime() |
OffsetDateTime toOffsetDateTime() |
Convertir a OffsetDateTime | zdt.toOffsetDateTime() |
Instant toInstant() |
Convertir a Instant | zdt.toInstant() |
Métodos de comparación
| Método | Descripción | Ejemplo |
|---|---|---|
boolean isAfter(ChronoZonedDateTime<?> other) |
Si es después de la fecha y hora especificadas | zdt1.isAfter(zdt2) |
boolean isBefore(ChronoZonedDateTime<?> other) |
Si es antes de la fecha y hora especificadas | zdt1.isBefore(zdt2) |
boolean isEqual(ChronoZonedDateTime<?> other) |
Si es igual a la fecha y hora especificadas | zdt1.isEqual(zdt2) |
int compareTo(ChronoZonedDateTime<?> other) |
Comparar dos fechas y horas | zdt1.compareTo(zdt2) |
Formateo y conversión a cadenas
| Métodos | Descripción | Ejemplo |
|---|---|---|
String format(DateTimeFormatter formatter) |
Formatear como cadena | zdt.format(DateTimeFormatter.ISO_ZONED_DATE_TIME) |
String toString() |
Convertir a cadena en formato ISO | "2023-06-15T14:30:45+08:00[Asia/Shanghai]" |