SimpleDateFormat

De ChuWiki

¿Qué es SimpleDateFormat en Java?[editar]

La clase SimpleDateFormat nos ayuda a convertir las fechas al formato de texto que queramos o a reconstruir la fecha a partir de la cadena de texto.

format(). Convertir un Date a String[editar]

Un uso simple de SimpleDateFormat para escribir una fecha en pantalla puede ser este

 import java.text.SimpleDateFormat;
 ...
 SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
 
 // Esto muestra la fecha actual en pantalla, más o menos así 26/10/2006
 System.out.println(formateador.format(new Date()));

Por supuesto, podemos jugar con la máscara y ponerla a nuestro gusto, dentro de las posibilidades que nos ofrece la API de SimpleDateFormat.

 SimpleDateFormat format1 = new SimpleDateFormat("'Hoy es' EEEEEEEEE dd 'de' MMMMM 'de' yyyy");
 SimpleDateFormat format2 = new SimpleDateFormat("dd/MM/yyyy");
 SimpleDateFormat format3 = new SimpleDateFormat("'Ingresaste' EEEEEEEEE dd 'de' MMMMM 'de' yyyy");

La siguiente tabla muestra todas las opciones para el formato de fecha

Letra Componente de Fecha u Hora Presentación Ejemplos
G Era designator Text AD
y Year Year 1996; 96
Y Week year Year 2009; 09
M Month in year (context sensitive) Month July; Jul; 07
L Month in year (standalone form) Month July; Jul; 07
w Week in year Number 27
W Week in month Number 2
D Day in year Number 189
d Day in month Number 10
F Day of week in month Number 2
E Day name in week Text Tuesday; Tue
u Day number of week (1 = Monday, ..., 7 = Sunday) Number 1
a Am/pm marker Text PM
H Hour in day (0-23) Number 0
k Hour in day (1-24) Number 24
K Hour in am/pm (0-11) Number 0
h Hour in am/pm (1-12) Number 12
m Minute in hour Number 30
s Second in minute Number 55
S Millisecond Number 978
z Time zone General time zone Pacific Standard Time; PST; GMT-08:00
Z Time zone RFC 822 time zone -0800
X Time zone ISO 8601 time zone -08; -0800; -08:00

parse(). Convertir un String a Date[editar]

Para reconstruir una fecha a partir de la cadena de texto, podemos usar la misma clase SimpleDateFormat, método parse(). Por ejemplo, si un usuario escribe una fecha con este formato en un JTextField, podemos leerla así

 import java.text.SimpleDateFormat;
 ...
 JTextField textField = new JTextField();
 ...
 SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
 try
 {
    Date fecha = formateador.parse(textField.getText());
 }
 catch (ParseException e)
 {
    // Error, la cadena de texto no se puede convertir en fecha.
 }

Aquí es importante fijarse en mayúsculas y minúsculas. Por ejemplo esto, salvo casos extraños, es incorrecto

 SimpleDateFormat formateador = new SimpleDateFormat("dd/mm/yyyy");

y seguramente debería ser

 SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");

debido a que mm se refiere a minutos y MM a meses.


SimpleDateFormat.setLenient()[editar]

Una cosa interesante es que a la hora de convertir un String a Date, la clase SimpleDateFormat es "indulgente", es decir, si metemos mal el String, trata de corregirlo. Por ejemplo, si introducimos una fecha "32 de Enero", no obtendremos error, sino que se arreglará y nos devolverá un Date correspondiente a "1 de Febrero". Podemos eliminar este comportamiento con el método setLenient(false);

 SimpleDateFormat formateador = new SimpleDateFormat("dd/MM/yyyy");
 formateador.setLenient(false);

de esta forma, el "32 de Enero" dará un error.

SimpleDateFormat Locale[editar]

SimpleDateFormat trabaja por defecto en el idioma del sistema operativo. Por ejemplo, si nuestro sistema operativo es español y ejecutamos el siguiente código

SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE MMMM d HH:mm:ss z yyyy");
System.out.println(dateFormat.format(new Date()));

obtendremos la siguiente salida

martes junio 18 07:39:34 CEST 2013

es decir, EEEE corresponde al día de la semana y lo obtenemos en español, mientras que MMMM corresponde al mes y lo obtenemos también en español (M da el mes con una cifra, por ejemplo, 6. MM lo da con dos, es decir, 06. MMM da tres letras del mes, es decir jun. MMMM da todas las letras del mes necesarias. De igual forma sucede con E, EE, EEE y EEEE para el día de la semana).

De igual forma, el método parse() de SimpleDateFormat espera en ese idioma por defecto (español en este caso) el día de la semana, mes, etc en el caso de que estén con texto y no con cifras. El siguiente código funcionará correctamente

 dateFormat.parse("martes junio 18 07:39:34 CEST 2013");

siendo dateFormat el SimpleDateFormat definido como en el trozo de código anterior.

Podemos cambiar este idioma por defecto en el momento de construir SimpleDateFormat, pasando un segundo parámetro con el Locale deseado. Por ejemplo, si con el sistema operativo en español usamos Locale.UK

SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE MMMM d HH:mm:ss z yyyy", Locale.UK);
String fecha = dateFormat.format(new Date());

el código de salida será

Tuesday June 18 07:45:18 CEST 2013

y nuestro ejemplo de parse() anterior

 dateFormat.parse("martes junio 18 07:39:34 CEST 2013");

fallará por tener los textos en español (martes y junio).

Aparte de los Locale definidos directamente el Locale, como Locale.UK, Locale.US, Locale.GERMAN, ... podemos construir nuestro propio Locale pasando dos parámetros al constructor de Locale, uno de idioma y otro de país, por ejemplo

 Locale espanol = new Locale("es","ES");

El método Locale.getAvailableLocales() nos permite saber que combinaciones de idioma/país son válidas. El siguiente código las muestra todas

Locale[] locales = Locale.getAvailableLocales();
for (Locale local:locales){
   System.out.println(local.getLanguage() + ", "+local.getCountry());
}

SimpleDateFormat TimeZone[editar]

SimpleDateFormat usa el TimeZone por defecto de tu sistema operativo, el siguiente código

SimpleDateFormat sdf = new SimpleDateFormat("dd/MM/YY HH:mm:ss zzzz");
System.out.println("Default Timezone " + sdf.getTimeZone().getID());

muestra en pantalla

Default Timezone Europe/Madrid

que es mi caso que vivo en la zona horaria de Europa Madrid.

Cuando convertimos String a Date o Date a String con SimpleDateFormat podemos cambiar en qué TimeZone se presenta sin necesidad de cambiar el Date que tengamos. El siguiente ejemplo maneja Date de Europe/Madrid (mi zona horaria), pero verás que el resultado se puede convertir y mostrar a GMT (Greenwich Meridian Time).

System.out.println(sdf.format(new Date()));
        
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(new Date()));

y la salida es

08/10/23 22:20:22 hora de verano de Europa central
08/10/23 20:20:22 hora del meridiano de Greenwich

Enlaces externos[editar]