Convertir la fecha de Java en formato de fecha XML (y viceversa)

¿Existe una forma sencilla y agradable de convertir una fecha de Java en formato de cadena de fecha XML y viceversa?

Aclamaciones,

Andez

Respuesta original

Supongo que aquí con “Formato de fecha XML” te refieres a algo así como “2010-11-04T19: 14Z”. En realidad es el formato ISO 8601 .

Puede convertirlo usando SimpleDateFormat, como otros sugirieron, FastDateFormat o usando Joda Time que creo que fue creado especialmente para este propósito .

Edición: muestras de código y más

Como earnshae declaró en un comentario, esta respuesta podría mejorarse con ejemplos.

Primero, tenemos que dejar claro que la respuesta original está bastante desactualizada. Es porque Java 8 introdujo las clases para manipular la fecha y la hora; el paquete java.time debería ser de interés. Si tienes la suerte de usar Java 8, debes usar uno de ellos. Sin embargo, estas cosas son sorprendentemente difíciles de acertar.

Fecha local (hora) que no es

Considera este ejemplo:

 LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T18:21"); System.out.println(dateTime); // 2016-03-23T18:21 

Al principio puede parecer que lo que estamos usando aquí es un local (para la fecha y hora del usuario). Sin embargo, si te atreves a preguntar, obtendrás un resultado diferente:

 System.out.println(dateTime.getChronology()); // ISO 

Esto en realidad, el tiempo ISO. Creo que debería leer ‘UTC’ pero, sin embargo, esto no tiene noción de zona horaria local. Así que deberíamos considerarlo universal.
Tenga en cuenta que no hay una “Z” al final de la cadena que estamos analizando. Si agrega algo aparte de la fecha y la hora, será recibido con java.time.format.DateTimeParseException . Así que parece que esta clase no sirve de nada si queremos analizar la cadena ISO8601.

ZonedDateTime al rescate

Afortunadamente, hay una clase que permite analizar cadenas ISO8601: es un java.time.ZonedDateTime .

 ZonedDateTime zonedDateTime = ZonedDateTime.parse("2016-03-23T18:21+01:00"); System.out.println(zonedDateTime); // 2016-03-23T18:21+01:00 ZonedDateTime zonedDateTimeZulu = ZonedDateTime.parse("2016-03-23T18:21Z"); System.out.println(zonedDateTimeZulu); // 2016-03-23T18:21Z 

El único problema aquí es que realmente necesita usar la designación de zona horaria. Intentar analizar el tiempo de fecha sin procesar (es decir, “2016-03-23T18: 21”) dará como resultado la ya mencionada RuntimeException . Dependiendo de la situación, tendrías que elegir entre LocalDateTime y ZonedDateTime .
Por supuesto, puedes convertir fácilmente entre esos dos, por lo que no debería ser un problema:

 System.out.println(zonedDateTimeZulu.toLocalDateTime()); // 2016-03-23T18:21 // Zone conversion ZonedDateTime cetDateTime = zonedDateTimeZulu.toLocalDateTime() .atZone(ZoneId.of("CET")); System.out.println(cetDateTime); // 2016-03-23T18:21+01:00[CET] 

Recomiendo usar estas clases hoy en día. Sin embargo, si la descripción de su trabajo incluye arqueología (lo que significa que no tiene la suerte de trabajar con Java 8 de más de 2 años …), es posible que necesite usar algo más.

La alegría de SimpleDateFormat

No soy un gran fan de https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html, pero a veces simplemente no tienes otra opción. El problema es que no es seguro para subprocesos y lanzará una Exception marcada (es decir, una Exception ParseException ) en su cara si no le gusta algo. Por lo tanto, el fragmento de código es bastante feo:

 private Object lock = new Object(); // ... try { synchronized (lock) { // Either "2016-03-23T18:21+01:00" or "2016-03-23T18:21Z" // will be correctly parsed (mind the different meaning though) Date date = dateFormat.parse("2016-03-23T18:21Z"); System.out.println(date); // Wed Mar 23 19:21:00 CET 2016 } } catch (ParseException e) { LOG.error("Date time parsing exception", e); } 

FastDateFormat

FastDateFormat está sincronizado, por lo tanto, al menos puede deshacerse del bloque sincronizado. Sin embargo, es una dependencia externa. Pero como se trata de Apache Commons Lang y se usa a fondo, supongo que es aceptable. En realidad es muy similar en uso a SimpleDateFormat :

 FastDateFormat fastDateFormat = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mmX"); try { Date fastDate = fastDateFormat.parse("2016-03-23T18:21+01:00"); System.out.println(fastDate); } catch (ParseException e) { LOG.error("Date time parsing exception", e); } 

JodaTime

Con Joda-Time puedes pensar que los siguientes trabajos:

 DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser(); LocalDateTime dateTime = LocalDateTime.parse("2016-03-23T20:48+01:00", parser); System.out.println(dateTime); // 2016-03-23T20:48:00.000 

Desafortunadamente, no importa lo que ponga en la última posición (Z, +03: 00, …) el resultado será el mismo. Claramente, no está funcionando.
Bueno, realmente debería analizarlo directamente:

 DateTimeFormatter parser = ISODateTimeFormat.dateTimeParser(); DateTime dateTime = parser.parseDateTime("2016-03-23T21:12:23+04:00"); System.out.println(dateTime); // 2016-03-23T18:12:23.000+01:00 

Ahora estará bien. Tenga en cuenta que, a diferencia de otras respuestas, utilicé dateTimeParser() y no dateTime() . Noté una diferencia sutil, pero importante en el comportamiento entre ellos (Joda-Time 2.9.2). Pero, lo dejo al lector para que lo pruebe y confirme.

Como ya se sugirió, use SimpleDateFormat.

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); String date = sdf.format(new Date()); System.out.println(date); Date d = sdf.parse(date); 

Mi conjetura es que el formato / patrón que busca es yyyy-MM-dd'T'HH:mm:ss También visite http://www.w3schools.com/schema/schema_dtypes_date.asp

Usando Joda Time harías lo siguiente:

 DateTimeFormatter fmt = ISODateTimeFormat.dateTime(); // ISO8601 (XML) Date/time DateTime dt = fmt.parseDateTime("2000-01-01T12:00:00+100"); // +1hr time zone System.out.println(fmt.print(dt)); // Prints in ISO8601 format 

Hilo seguro, inmutable y sencillo.

Solo usando SimpleDateFormat en java podemos hacer esto …

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); Date date = sdf.parse("2011-12-31T15:05:50+1000"); 

El método perfecto, usa XMLGregorianCalendar:

 GregorianCalendar calendar = new GregorianCalendar(); calendar.setTime(v); DatatypeFactory df = DatatypeFactory.newInstance(); XMLGregorianCalendar dateTime = df.newXMLGregorianCalendar(calendar); return dateTime.toString(); 

Puede analizar y formatear fechas desde y hacia cualquier formato usando SimpleDateFormat

Recomendaría usar el java incorporado en la clase javax.xml.bind.DatatypeConverter . Puede manejar la conversión hacia y desde la mayoría de los tipos XML simples. Es un poco engorroso para las fechas que tiene que pasar por un objeto de Calendar pero por otro lado maneja todas las variantes de información de zona que pueden ocurrir en un campo de datetime xml.

Desde xml:

  Calendar c = DatatypeConverter.parseDateTime("2015-10-21T13:25"); Date d = c.getTime(); 

A xml:

  Date yourDate = new Date() Calendar c = Calendar.getInstance(); c.setTime(yourDate); String xmlDateTime = DatatypeConverter.printDateTime(c); 

Para cumplir con ISO8601, la zona horaria debe estar en el formato + HH: MM o – HH: MM

Con Simpledateformat debe usar XXX en lugar de Z (vea la respuesta de NovelGuy)

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX"); 

Sin saber exactamente qué formato necesita, la respuesta genérica es: va a querer DateFormat o SimpleDateFormat. Hay un buen tutorial en ambos aquí .