java.util.Fecha a XMLGregorianCalendar
¿No existe una manera conveniente de pasar de java.util.Date a XMLGregorianCalendar?
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
Para aquellos que podrían terminar aquí buscando la conversión opuesta (de XMLGregorianCalendar
a Date
):
XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();
Me gustaría dar un paso atrás y dar una mirada moderna a esta pregunta que data de hace 10 años. Las clases mencionadas Date
y XMLGregorianCalendar
ya son antiguas. Desafío el uso de ellos y ofrezco alternativas.
Date
Siempre estuvo mal diseñado y tiene más de 20 años. Esto es simple: no lo uses.XMLGregorianCalendar
También es antiguo y tiene un diseño anticuado. Según tengo entendido, se utilizó para producir fechas y horas en formato XML para documentos XML. Me gusta2009-05-07T19:05:45.678+02:00
o2009-05-07T17:05:45.678Z
. Estos formatos concuerdan lo suficientemente bien con ISO 8601 como para que las clases de java.time, la API moderna de fecha y hora de Java, puedan producirlos, lo cual preferimos.
No es necesaria ninguna conversión
Para muchos (¿la mayoría?) propósitos, el reemplazo moderno de a Date
será un Instant
. An Instant
es un punto en el tiempo (tal como a Date
es).
Instant yourInstant = // ...
System.out.println(yourInstant);
Un ejemplo de resultado de este fragmento:
2009-05-07T17:05:45.678Z
Es lo mismo que la última de mis XMLGregorianCalendar
cadenas de ejemplo anteriores. Como la mayoría de ustedes saben, proviene de Instant.toString
ser llamado implícitamente por System.out.println
. Con java.time, en muchos casos no necesitamos las conversiones que en los viejos tiempos hacíamos entre Date
, y otras clases (aunque en algunos casos sí necesitamos conversiones Calendar
, XMLGregorianCalendar
les mostraré un par en la siguiente sección) .
Controlando el desplazamiento
Ni a Date
ni in Instant
tienen zona horaria ni desplazamiento UTC. La respuesta previamente aceptada y aún más votada de Ben Noland utiliza la zona horaria predeterminada actual de la JVM para seleccionar el desplazamiento del archivo XMLGregorianCalendar
. Para incluir un desplazamiento en un objeto moderno utilizamos un archivo OffsetDateTime
. Por ejemplo:
ZoneId zone = ZoneId.of("America/Asuncion");
OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
System.out.println(dateTime);
2009-05-07T13:05:45.678-04:00
Nuevamente esto se ajusta al formato XML. Si desea volver a utilizar la configuración de zona horaria actual de JVM, configúrela zone
en ZoneId.systemDefault()
.
¿Qué pasa si necesito absolutamente un XMLGregorianCalendar?
Hay más formas de convertir Instant
a XMLGregorianCalendar
. Presentaré un par, cada uno con sus pros y sus contras. Primero, así como an XMLGregorianCalendar
produce una cadena como 2009-05-07T17:05:45.678Z
, también se puede construir a partir de dicha cadena:
String dateTimeString = yourInstant.toString();
XMLGregorianCalendar date2
= DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
System.out.println(date2);
2009-05-07T17:05:45.678Z
Ventaja: es corto y no creo que dé sorpresas. Desventaja: Para mí, se siente como un desperdicio formatear el instante en una cadena y analizarlo nuevamente.
ZonedDateTime dateTime = yourInstant.atZone(zone);
GregorianCalendar c = GregorianCalendar.from(dateTime);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
System.out.println(date2);
2009-05-07T13:05:45.678-04:00
Ventaja: es la conversión oficial. Controlar el desplazamiento es algo natural. Desventaja: pasa por más pasos y, por lo tanto, es más largo.
¿Qué pasa si tenemos una cita?
Si obtuvo un objeto antiguo Date
de una API heredada que no puede permitirse el lujo de cambiar en este momento, conviértalo a Instant
:
Instant i = yourDate.toInstant();
System.out.println(i);
La salida es la misma que antes:
2009-05-07T17:05:45.678Z
Si desea controlar el desplazamiento, convierta más a an OffsetDateTime
de la misma manera que antes.
Si tiene un método antiguo Date
y lo necesita absolutamente XMLGregorianCalendar
, simplemente use la respuesta de Ben Noland.
Enlaces
- Tutorial de Oracle: Fecha y hora que explica cómo utilizar java.time.
- Tipos de datos XSD de fecha y hora en W3Schools.
- Artículo de Wikipedia: ISO 8601
A continuación se muestra un método para convertir de GregorianCalendar a XMLGregorianCalendar; Dejaré la parte de convertir de java.util.Date a GregorianCalendar como ejercicio para ti:
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
public class DateTest {
public static void main(final String[] args) throws Exception {
GregorianCalendar gcal = new GregorianCalendar();
XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
.newXMLGregorianCalendar(gcal);
System.out.println(xgcal);
}
}
EDITAR: Lentamente :-)