Clase Java DateTimeFormatter

DateTimeFormatter es una clase importante en la API de fecha y hora introducida en Java 8 (paquete java.time), utilizada para formatear y analizar objetos de fecha y hora. Esta clase proporciona potentes funciones para manejar la visualización y conversión de fechas y horas.

En pocas palabras, DateTimeFormatter tiene principalmente dos funciones:

  • Formatear: convertir objetos de fecha y hora (como LocalDate, LocalDateTime) en cadenas con un formato específico.
  • Analizar: convertir cadenas que coinciden con el formato en objetos de fecha y hora.

¿Por qué se necesita DateTimeFormatter?

Antes de Java 8, usábamos SimpleDateFormat para el formateo y análisis de fechas, pero tenía varias desventajas:

  • No era seguro para subprocesos.
  • Su diseño era bastante anticuado.
  • El manejo de errores no era amigable.

DateTimeFormatter resuelve estos problemas:

  • Seguridad para subprocesos: se puede compartir la instancia de forma segura en entornos de múltiples subprocesos.
  • Inmutable: una vez creado, no se puede modificar.
  • Formatos predefinidos más ricos: proporciona una gran cantidad de formatos integrados.
  • Mejor manejo de errores: cuando el análisis falla, proporciona mensajes de error más detallados.

Uso básico

Formateadores predefinidos

DateTimeFormatter proporciona muchas constantes de formateo predefinidas:

Ejemplo

LocalDateTime now = LocalDateTime.now();

// Usando el formateador predefinido
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE));     // 2023-11-15
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_TIME));     // 14:30:45.123
System.out.println(now.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); // 2023-11-15T14:30:45.123

Patrones personalizados

Puedes crear formateadores personalizados utilizando cadenas de patrón:

Ejemplo

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formattedDateTime = now.format(formatter);  // Formatear
System.out.println(formattedDateTime);             // 2023-11-15 14:30:45

// Analizar
LocalDateTime parsedDateTime = LocalDateTime.parse("2023-11-15 14:30:45", formatter);

// Formato de fecha chino común
DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern(yyyyañoMMmesdddía);
String formattedDate = today.format(chineseFormatter);
System.out.println(Fecha en formato chino: + formattedDate);

// Analizando una cadena de fecha en chino
String chineseDateStr = 2023año05mes20día;
LocalDate parsedDate = LocalDate.parse(chineseDateStr, chineseFormatter);
System.out.println(Fecha analizada: + parsedDate);

// Otros formatos comunes
DateTimeFormatter formatter1 = DateTimeFormatter.ofPattern("yyyy-MM-dd");
DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/dd/yyyy");
DateTimeFormatter formatter3 = DateTimeFormatter.ofPattern(yyyyañoMMmesdddía EEEE, Locale.CHINA);

System.out.println(Formato 1: + today.format(formatter1));
System.out.println(Formato 2: + today.format(formatter2));
System.out.println(Formato 3 (con día de la semana): + today.format(formatter3));

Formato localizado

Puedes crear formateadores según diferentes regiones:

Ejemplo

DateTimeFormatter frenchFormatter =
    DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG)
                     .withLocale(Locale.FRENCH);
String frenchDate = now.format(frenchFormatter);
System.out.println(frenchDate);  // 15 novembre 2023

Explicación de las letras del patrón

Al crear formatos personalizados, debes utilizar letras de patrón específicas:

Letra Significado Ejemplo
y año yyyy → 2023
M mes MM → 11
d día dd → 15
H Hora (0-23) HH → 14
h Hora (1-12) hh → 02
m Minuto mm → 30
s segundo ss → 45
S Milisegundo SSS → 123
E Día de la semana E → miércoles
a AM/PM a → tarde

Mejores prácticas

Reutilizar formateadores

Dado que DateTimeFormatter es seguro para subprocesos, se recomienda definir los formateadores de uso común como constantes:

Ejemplo

public class DateUtils {
    public static final DateTimeFormatter STANDARD_FORMATTER =
        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
   
    // Forma de uso
    String formatted = LocalDateTime.now().format(STANDARD_FORMATTER);
}

Ejemplo completo:

Ejemplo

import java.time.LocalDate;
import java.time.LocalTime;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class EjemploTest {

    public static void main(String[] args) {
        // 1. Ejemplo de LocalDate
        LocalDate currentDate = LocalDate.now();
        System.out.println(Fecha actual: + currentDate);
       
        LocalDate specificDate = LocalDate.of(2023, 5, 20);
        System.out.println(Fecha específica: + specificDate);

        // 2. Ejemplo de LocalTime
        LocalTime currentTime = LocalTime.now();
        System.out.println(Hora actual: + currentTime);
       
        LocalTime specificTime = LocalTime.of(14, 30, 15);
        System.out.println(Hora específica: + specificTime);

        // 3. Ejemplo de LocalDateTime
        LocalDateTime currentDateTime = LocalDateTime.now();
        System.out.println(Fecha y hora actuales: + currentDateTime);
       
        LocalDateTime specificDateTime = LocalDateTime.of(2023, 5, 20, 14, 30, 15);
        System.out.println(Fecha y hora específicas: + specificDateTime);

        // 4. Ejemplo de DateTimeFormatter
        // Formateo básico
        DateTimeFormatter basicFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        System.out.println(Formato básico: + currentDate.format(basicFormatter));

        // Formateo en chino
        DateTimeFormatter chineseFormatter = DateTimeFormatter.ofPattern(yyyyañoMMmesdddía, Locale.CHINA);
        System.out.println(Fecha en chino: + currentDate.format(chineseFormatter));

        // Formateo en chino con día de la semana
        DateTimeFormatter weekFormatter = DateTimeFormatter.ofPattern(yyyyañoMMmesdddía EEEE, Locale.CHINA);
        System.out.println(Fecha en chino con día de la semana: + currentDate.format(weekFormatter));

        // Formateo de hora
        DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHCuandommdividirsssegundo);
        System.out.println(Hora en chino: + currentTime.format(timeFormatter));

        // Formateo de fecha y hora
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        System.out.println(Fecha y hora estándar: + currentDateTime.format(dateTimeFormatter));

        // Analizar fecha
        String dateStr = "2023-05-20";
        LocalDate parsedDate = LocalDate.parse(dateStr, basicFormatter);
        System.out.println(Fecha analizada: + parsedDate);

        // Analizar fecha en chino
        String chineseDateStr = 2023año05mes20día;
        LocalDate parsedChineseDate = LocalDate.parse(chineseDateStr, chineseFormatter);
        System.out.println(Fecha en chino analizada: + parsedChineseDate);
    }
}

El resultado de la salida es:

当前日期: 2025-05-01
特定日期: 2023-05-20
当前时间: 10:46:38.591747
特定时间: 14:30:15
当前日期时间: 2025-05-01T10:46:38.592002
特定日期时间: 2023-05-20T14:30:15
基本格式化: 2025-05-01
中文日期: 2025年05月01日
带星期的中文日期: 2025年05月01日 星期四
中文时间: 10时46分38秒
标准日期时间: 2025-05-01 10:46:38
解析后的日期: 2023-05-20
解析后的中文日期: 2023-05-20

Manejo de excepciones de análisis

Al analizar cadenas, debes manejar las posibles excepciones:

Ejemplo

try {
    LocalDateTime dateTime = LocalDateTime.parse("2023-11-15", formatter);
} catch (DateTimeParseException e) {
    System.err.println(No se pudo analizar la fecha y hora: + e.getMessage());
}

Considerar la zona horaria

Si necesitas manejar zonas horarias, puedes usarZonedDateTimey patrones de zona horaria específicos:

Ejemplo

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss z");
ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
System.out.println(zonedDateTime.format(formatter));  // 2023-11-15 14:30:45 CST

Resumen

DateTimeFormatter es una poderosa herramienta para el formateo y análisis en la API de fecha y hora de Java 8. En comparación con el antiguo SimpleDateFormat, es más seguro, flexible y fácil de usar. Dominar el uso de DateTimeFormatter te permite manejar de manera más eficiente diversas necesidades de formatos de fecha y hora.

Recuerda los puntos clave:

  • Utiliza formateadores predefinidos para formatos comunes.
  • Utiliza ofPattern() para crear formatos personalizados.
  • Considera los requisitos de localización y zona horaria.
  • Reutiliza instancias de formateadores seguros para subprocesos.
  • Maneja correctamente las excepciones de análisis.
Otras extensiones