FYI: Ambas clases terribles fueron suplantadas hace años por las clases java.time definidas en JSR 310. Vea la ZonedDateTimeclase y los nuevos métodos de conversión agregados a las clases heredadas. Detalles en esta respuesta por Ole VV
Basil Bourque
Respuestas:
36
Me gustaría dar un paso atrás y una mirada moderna a esta pregunta de 10 años. Las clases mencionadas, Datey XMLGregorianCalendar, son viejas ahora. Desafío el uso de ellos y ofrezco alternativas.
Datesiempre fue mal diseñado y tiene más de 20 años. Esto es simple: no lo use.
XMLGregorianCalendares viejo también y tiene un diseño anticuado. Según tengo entendido, se utilizó para producir fechas y horas en formato XML para documentos XML. Me gusta 2009-05-07T19:05:45.678+02:00o 2009-05-07T17:05:45.678Z. Estos formatos concuerdan bastante bien con ISO 8601 que las clases de java.time, la API moderna de fecha y hora de Java, pueden producirlos, lo que preferimos.
No es necesaria conversión
Para muchos (¿la mayoría?), El reemplazo moderno de un Dateserá un Instant. Un Instantes un punto en el tiempo (tal como Datees).
Es lo mismo que la última de mis XMLGregorianCalendarcadenas de ejemplo anteriores. Como la mayoría de ustedes saben, proviene de Instant.toStringser llamado implícitamente por System.out.println. Con java.time, en muchos casos no necesitamos las conversiones que en los viejos tiempos que hicimos entre Date, Calendar, XMLGregorianCalendary otras clases (en algunos casos que hacemos conversiones necesidad, sin embargo, estoy mostrando un par en la siguiente sección) .
Controlando el desplazamiento
Ni a Dateni in Instanttiene una zona horaria ni un desplazamiento UTC. La respuesta previamente aceptada y aún más votada por Ben Noland utiliza la zona horaria predeterminada actual de JVM para seleccionar el desplazamiento de la XMLGregorianCalendar. Para incluir un desplazamiento en un objeto moderno, usamos un 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 JVM actual, configure zoneen ZoneId.systemDefault().
¿Qué sucede si realmente necesito un XMLGregorianCalendar?
Hay más maneras de convertir Instanta XMLGregorianCalendar. Presentaré una pareja, cada una con sus ventajas y desventajas. Primero, así como un XMLGregorianCalendarproduce una cadena como 2009-05-07T17:05:45.678Z, también se puede construir a partir de dicha cadena:
¿Es seguro mantener getInstance () como una variable estática en alguna clase de convertidor? Traté de buscarlo en JavaDoc pero no pude encontrar nada. ¿Es difícil saber si habrá problemas en el uso concurrente?
Martin
36
Si está dispuesto a usar JodaTime, puede hacerlo en una línea: DatatypeFactory.newInstance (). NewXMLGregorianCalendar (new DateTime (). ToGregorianCalendar ())
Tenga en cuenta que Calendar no es seguro para subprocesos y, por lo tanto, tampoco GregorianCalender. Ver también stackoverflow.com/questions/12131324/…
cuestionario
Versión de una línea: DatatypeFactory.newInstance (). NewXMLGregorianCalendar (new GregorianCalendar () {{setTime (yourDate);}})
Alex Vayda
205
Para aquellos que podrían terminar aquí buscando la conversión opuesta (de XMLGregorianCalendara Date):
Aquí hay un método para convertir de un GregorianCalendar a XMLGregorianCalendar; Dejaré la parte de convertir de java.util.Date a GregorianCalendar como ejercicio para ti:
Solo pensé en agregar mi solución a continuación, ya que las respuestas anteriores no satisfacían mis necesidades exactas. Mi esquema Xml requería elementos separados de fecha y hora, no un solo campo de fecha y hora. El constructor estándar XMLGregorianCalendar utilizado anteriormente generará un campo DateTime
Tenga en cuenta que hay un par de gothca, como tener que agregar uno al mes (ya que Java cuenta meses desde 0).
Espero que mi codificación sea correcta; D Para hacerlo más rápido, simplemente use la llamada fea getInstance () de GregorianCalendar en lugar de la llamada del constructor:
import java.util.GregorianCalendar;import javax.xml.datatype.DatatypeFactory;import javax.xml.datatype.XMLGregorianCalendar;publicclassDateTest{publicstaticvoid main(finalString[] args)throwsException{// do not forget the type cast :/GregorianCalendar gcal =(GregorianCalendar)GregorianCalendar.getInstance();XMLGregorianCalendar xgcal =DatatypeFactory.newInstance().newXMLGregorianCalendar(gcal);System.out.println(xgcal);}}
-1 para usar .getInstance (). GregorianCalendar.getInstance()es el equivalente de Calendar.getInstance(). No Calendar.getInstance()puede hacerlo más rápido, porque usa lo mismo new GregorianCalendar(), pero antes también comprueba la configuración regional predeterminada y podría crear un calendario japonés o budista, ¡así que para algunos usuarios afortunados lo será ClassCastException!
kan
6
Suponiendo que está decodificando o codificando xml y está utilizando JAXB, entonces es posible reemplazar el enlace dateTime por completo y usar algo más que 'XMLGregorianCalendar' para cada fecha en el esquema.
De esa manera, puede JAXBhacer las cosas repetitivas mientras puede pasar el tiempo escribiendo código increíble que brinde valor.
Ejemplo de jodatime DateTime: (Hacer esto con java.util.Date también funcionaría, pero con ciertas limitaciones. Prefiero jodatime y está copiado de mi código, así que sé que funciona ...)
Si está contento de mapear a un instante en función de la zona horaria + marca de tiempo, y la zona horaria original no es realmente relevante, entonces java.util.Dateprobablemente también esté bien.
ZonedDateTime
clase y los nuevos métodos de conversión agregados a las clases heredadas. Detalles en esta respuesta por Ole VVRespuestas:
Me gustaría dar un paso atrás y una mirada moderna a esta pregunta de 10 años. Las clases mencionadas,
Date
yXMLGregorianCalendar
, son viejas ahora. Desafío el uso de ellos y ofrezco alternativas.Date
siempre fue mal diseñado y tiene más de 20 años. Esto es simple: no lo use.XMLGregorianCalendar
es viejo también 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 bastante bien con ISO 8601 que las clases de java.time, la API moderna de fecha y hora de Java, pueden producirlos, lo que preferimos.No es necesaria conversión
Para muchos (¿la mayoría?), El reemplazo moderno de un
Date
será unInstant
. UnInstant
es un punto en el tiempo (tal comoDate
es).Un ejemplo de salida de este fragmento:
Es lo mismo que la última de mis
XMLGregorianCalendar
cadenas de ejemplo anteriores. Como la mayoría de ustedes saben, proviene deInstant.toString
ser llamado implícitamente porSystem.out.println
. Con java.time, en muchos casos no necesitamos las conversiones que en los viejos tiempos que hicimos entreDate
,Calendar
,XMLGregorianCalendar
y otras clases (en algunos casos que hacemos conversiones necesidad, sin embargo, estoy mostrando un par en la siguiente sección) .Controlando el desplazamiento
Ni a
Date
ni inInstant
tiene una zona horaria ni un desplazamiento UTC. La respuesta previamente aceptada y aún más votada por Ben Noland utiliza la zona horaria predeterminada actual de JVM para seleccionar el desplazamiento de laXMLGregorianCalendar
. Para incluir un desplazamiento en un objeto moderno, usamos unOffsetDateTime
. Por ejemplo:Nuevamente, esto se ajusta al formato XML. Si desea volver a utilizar la configuración de zona horaria JVM actual, configure
zone
enZoneId.systemDefault()
.¿Qué sucede si realmente necesito un XMLGregorianCalendar?
Hay más maneras de convertir
Instant
aXMLGregorianCalendar
. Presentaré una pareja, cada una con sus ventajas y desventajas. Primero, así como unXMLGregorianCalendar
produce una cadena como2009-05-07T17:05:45.678Z
, también se puede construir a partir de dicha cadena:Pro: es breve y no creo que dé sorpresas. Con: Para mí, se siente como un desperdicio formatear el instante en una cadena y analizarlo nuevamente.
Pro: es la conversión oficial. Controlar el desplazamiento es algo natural. Con: pasa por más pasos y, por lo tanto, es más largo.
¿Qué pasa si tenemos una cita?
Si obtuvo un
Date
objeto antiguo de una API heredada que no puede permitirse cambiar en este momento, conviértalo aInstant
:La salida es la misma que antes:
Si desea controlar el desplazamiento, convierta más a
OffsetDateTime
a de la misma manera que arriba.Si tienes un anticuado
Date
y necesitas un anticuadoXMLGregorianCalendar
, usa la respuesta de Ben Noland.Enlaces
fuente
fuente
Para aquellos que podrían terminar aquí buscando la conversión opuesta (de
XMLGregorianCalendar
aDate
):fuente
Aquí hay un método para convertir de un GregorianCalendar a XMLGregorianCalendar; Dejaré la parte de convertir de java.util.Date a GregorianCalendar como ejercicio para ti:
EDITAR: Slooow :-)
fuente
Un ejemplo de una línea usando la biblioteca Joda-Time :
Gracias a Nicolas Mommaerts por su comentario en la respuesta aceptada .
fuente
Solo pensé en agregar mi solución a continuación, ya que las respuestas anteriores no satisfacían mis necesidades exactas. Mi esquema Xml requería elementos separados de fecha y hora, no un solo campo de fecha y hora. El constructor estándar XMLGregorianCalendar utilizado anteriormente generará un campo DateTime
Tenga en cuenta que hay un par de gothca, como tener que agregar uno al mes (ya que Java cuenta meses desde 0).
fuente
Espero que mi codificación sea correcta; D Para hacerlo más rápido, simplemente use la llamada fea getInstance () de GregorianCalendar en lugar de la llamada del constructor:
fuente
GregorianCalendar.getInstance()
es el equivalente deCalendar.getInstance()
. NoCalendar.getInstance()
puede hacerlo más rápido, porque usa lo mismonew GregorianCalendar()
, pero antes también comprueba la configuración regional predeterminada y podría crear un calendario japonés o budista, ¡así que para algunos usuarios afortunados lo seráClassCastException
!Suponiendo que está decodificando o codificando xml y está utilizando
JAXB
, entonces es posible reemplazar el enlace dateTime por completo y usar algo más que 'XMLGregorianCalendar' para cada fecha en el esquema.De esa manera, puede
JAXB
hacer las cosas repetitivas mientras puede pasar el tiempo escribiendo código increíble que brinde valor.Ejemplo de jodatime
DateTime
: (Hacer esto con java.util.Date también funcionaría, pero con ciertas limitaciones. Prefiero jodatime y está copiado de mi código, así que sé que funciona ...)Y el convertidor:
Vea aquí: ¿cómo reemplazar XmlGregorianCalendar por fecha?
Si está contento de mapear a un instante en función de la zona horaria + marca de tiempo, y la zona horaria original no es realmente relevante, entonces
java.util.Date
probablemente también esté bien.fuente
Mira este código: -
Puedes ver el ejemplo completo aquí
fuente