1. DateTimeFormatter: qué es y para qué sirve
En los programas reales, las fechas rara vez viven solo dentro del código. Normalmente hay que:
- Convertirlas en cadena para mostrarlas en la consola, en pantalla o en un archivo (por ejemplo, "01.06.2025 14:30").
- Analizar una cadena, es decir, convertir una cadena introducida por el usuario o llegada desde un archivo de vuelta a un objeto de fecha/hora.
Para ello, en Java hay una herramienta potente y cómoda — la clase java.time.format.DateTimeFormatter.
Se puede decir que DateTimeFormatter es un traductor entre objetos de tiempo (LocalDate, LocalDateTime, ZonedDateTime, Instant, etc.) y cadenas. Puede:
- Convertir objetos de fecha/hora en cadenas en el formato deseado (format — formateo).
- Convertir cadenas en objetos de fecha/hora (parse — análisis).
2. Formateadores estándar: rápido y sencillo
Java ha preparado para nosotros un conjunto de formateadores estándar que cubren los formatos ISO más populares (estándares internacionales para fechas y horas).
Estos son algunos de ellos:
| Formateador | Ejemplo de cadena | Descripción |
|---|---|---|
|
2025-06-01 | Solo fecha (año-mes-día) |
|
14:30:00 | Solo hora (horas:minutos:seg) |
|
2025-06-01T14:30:00 | Fecha y hora sin zona horaria |
|
2025-06-01T14:30:00+03:00[Europe/Minsk] | Fecha, hora y zona horaria |
Ejemplo de uso de un formateador estándar
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class FormatterDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.now();
// Formateamos la fecha a una cadena
String text = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(text); // Por ejemplo, 2025-06-01
// Analizamos la cadena de vuelta a una fecha
LocalDate parsed = LocalDate.parse("2025-06-01", DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(parsed); // 2025-06-01
}
}
Analogía
Si Java fuera una cafetería, los formateadores estándar serían «americano», «latte» y «espresso». Rápido y estándar, ¡pero a veces apetece algo más especial!
3. Patrones personalizados: DateTimeFormatter.ofPattern
A veces los formatos estándar no son suficientes. Por ejemplo, hay que mostrar la fecha como "01.06.2025 14:30", y no como "2025-06-01T14:30:00". Para ello podemos crear nuestro propio patrón con el método DateTimeFormatter.ofPattern(String pattern).
Sintaxis de los patrones
En el patrón se usan letras especiales:
- y — año (yyyy — 2025)
- M — mes (MM — 06)
- d — día (dd — 01)
- H — hora (formato de 24 horas, HH — 14)
- m — minutos (mm — 30)
- s — segundos (ss — 00)
Ejemplos de patrones
| Patrón | Ejemplo del resultado |
|---|---|
|
01.06.2025 |
|
2025/06/01 |
|
01.06.2025 14:30 |
|
2025-06-01 14:30:00 |
|
1 junio 2025 (con la configuración regional rusa) |
Ejemplo: formateo de fecha y hora
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class CustomFormatDemo {
public static void main(String[] args) {
LocalDateTime dt = LocalDateTime.of(2025, 6, 1, 14, 30);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
String text = dt.format(formatter);
System.out.println(text); // 01.06.2025 14:30
}
}
Ejemplo: analizar una cadena a fecha
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dt = LocalDateTime.parse(input, formatter);
System.out.println(dt); // 2025-06-01T14:30
}
}
Atención: ¡el patrón debe coincidir exactamente con la cadena! Si la cadena incluye segundos — añada :ss al patrón.
4. Formateo: convertimos fecha/hora en cadena
Esquema general
- Crear el objeto necesario (LocalDate, LocalDateTime, ZonedDateTime, etc.).
- Crear o elegir el formateador adecuado.
- Invocar en el objeto el método format(DateTimeFormatter) y obtener la cadena.
Ejemplo: mostramos la fecha en distintos formatos
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class MultiFormatDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
// ISO estándar
System.out.println(date.format(DateTimeFormatter.ISO_LOCAL_DATE)); // 2025-06-01
// Formato personalizado
DateTimeFormatter rusFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
System.out.println(date.format(rusFormat)); // 01.06.2025
// Estilo estadounidense
DateTimeFormatter usFormat = DateTimeFormatter.ofPattern("MM/dd/yyyy");
System.out.println(date.format(usFormat)); // 06/01/2025
}
}
Formateo de hora
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
public class TimeFormatDemo {
public static void main(String[] args) {
LocalTime time = LocalTime.of(14, 30, 5);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("HH:mm:ss");
System.out.println(time.format(formatter)); // 14:30:05
}
}
5. Análisis: convertimos una cadena en fecha/hora
Esquema general
- Obtener la cadena (por ejemplo, del usuario).
- Crear un formateador con el mismo patrón que la cadena.
- Llamar al método estático parse() o al método parse() del formateador.
Ejemplo: analizar una fecha
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class ParseDateDemo {
public static void main(String[] args) {
String input = "01.06.2025";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date); // 2025-06-01
}
}
Ejemplo: analizar fecha y hora
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
public class ParseDateTimeDemo {
public static void main(String[] args) {
String input = "01.06.2025 14:30";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy HH:mm");
LocalDateTime dateTime = LocalDateTime.parse(input, formatter);
System.out.println(dateTime); // 2025-06-01T14:30
}
}
6. Manejo de errores de análisis
El análisis puede ser traicionero. Si la cadena no se ajusta al patrón, Java lanzará la excepción DateTimeParseException. Es una situación habitual, por ejemplo, si el usuario introduce una fecha con un error.
Ejemplo: manejo de errores al analizar
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class ParseErrorDemo {
public static void main(String[] args) {
String input = "32.13.2025"; // Fecha no válida
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd.MM.yyyy");
try {
LocalDate date = LocalDate.parse(input, formatter);
System.out.println(date);
} catch (DateTimeParseException ex) {
System.out.println("Error de análisis: " + ex.getMessage());
}
}
}
Importante: ¡siempre gestione este tipo de errores si trabaja con entrada del usuario!
7. Práctica: transformación de fechas para el usuario
Supongamos que en nuestra aplicación de aprendizaje hay una tarea: el usuario introduce la fecha de nacimiento en el formato "dd.MM.yyyy", y el programa debe mostrar la fecha en el formato "yyyy/MM/dd", así como el día de la semana.
Ejemplo
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Scanner;
public class BirthdayFormatDemo {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
System.out.print("Introduzca la fecha de nacimiento (dd.MM.yyyy): ");
String input = scanner.nextLine();
DateTimeFormatter inputFormat = DateTimeFormatter.ofPattern("dd.MM.yyyy");
DateTimeFormatter outputFormat = DateTimeFormatter.ofPattern("yyyy/MM/dd");
try {
LocalDate birthday = LocalDate.parse(input, inputFormat);
String formatted = birthday.format(outputFormat);
System.out.println("Su fecha en el nuevo formato: " + formatted);
System.out.println("Día de la semana: " + birthday.getDayOfWeek()); // Por ejemplo, SATURDAY
} catch (DateTimeParseException ex) {
System.out.println("Error: ¡formato de fecha no válido!");
}
}
}
8. Localización: cómo influye el idioma en el formateo
Con DateTimeFormatter no solo puede cambiar el orden de los números, sino también mostrar el mes con palabras, el día de la semana, etc. Se tiene en cuenta la configuración regional (idioma y región).
Ejemplo: mostrar el mes con palabras en ruso
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", new Locale("ru"));
System.out.println(date.format(formatter)); // 1 junio 2025
}
}
Ejemplo: configuración regional inglesa
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class LocaleEnDemo {
public static void main(String[] args) {
LocalDate date = LocalDate.of(2025, 6, 1);
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.ENGLISH);
System.out.println(date.format(formatter)); // 1 June 2025
}
}
Truco: si quiere que el mes y el día de la semana estén en el idioma deseado — ¡indique la configuración regional explícitamente!
9. Errores típicos al formatear y analizar fechas
Error n.º 1: el patrón no coincide con la cadena.
Si la cadena es "01.06.2025 14:30" y el patrón "dd.MM.yyyy", el análisis fallará. El patrón debe coincidir exactamente con la cadena.
Error n.º 2: confundir los símbolos del patrón.
MM — mes, mm — minutos. Si escribe "dd.mm.yyyy", Java pensará que quiere minutos y dará un error. Para el mes use siempre la M mayúscula.
Error n.º 3: excepciones no gestionadas durante el análisis.
Si no captura DateTimeParseException, el programa podría finalizar de forma inesperada ante una entrada incorrecta del usuario. Gestione siempre estos errores.
Error n.º 4: no indicar la configuración regional al usar palabras.
Si usa un patrón con el mes en palabras (MMMM) y no indica la configuración regional, Java puede usar el idioma por defecto (por ejemplo, inglés). Indique siempre la configuración regional necesaria.
Error n.º 5: usar clases antiguas (SimpleDateFormat, Date) en proyectos nuevos.
Recuerde: en código moderno use solo java.time y DateTimeFormatter.
GO TO FULL VERSION