Estou procurando um método simples de conversão entre java.util.Date e javax.xml.datatype.XMLGregorianCalendar em ambas as direções.
Aqui está o código que estou usando agora :
import java.util.GregorianCalendar;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.datatype.DatatypeFactory;
import javax.xml.datatype.XMLGregorianCalendar;
/**
* Utility class for converting between XMLGregorianCalendar and java.util.Date
*/
public class XMLGregorianCalendarConverter {
/**
* Needed to create XMLGregorianCalendar instances
*/
private static DatatypeFactory df = null;
static {
try {
df = DatatypeFactory.newInstance();
} catch (DatatypeConfigurationException dce) {
throw new IllegalStateException(
"Exception while obtaining DatatypeFactory instance", dce);
}
}
/**
* Converts a java.util.Date into an instance of XMLGregorianCalendar
*
* @param date Instance of java.util.Date or a null reference
* @return XMLGregorianCalendar instance whose value is based upon the
* value in the date parameter. If the date parameter is null then
* this method will simply return null.
*/
public static XMLGregorianCalendar asXMLGregorianCalendar(java.util.Date date) {
if (date == null) {
return null;
} else {
GregorianCalendar gc = new GregorianCalendar();
gc.setTimeInMillis(date.getTime());
return df.newXMLGregorianCalendar(gc);
}
}
/**
* Converts an XMLGregorianCalendar to an instance of java.util.Date
*
* @param xgc Instance of XMLGregorianCalendar or a null reference
* @return java.util.Date instance whose value is based upon the
* value in the xgc parameter. If the xgc parameter is null then
* this method will simply return null.
*/
public static java.util.Date asDate(XMLGregorianCalendar xgc) {
if (xgc == null) {
return null;
} else {
return xgc.toGregorianCalendar().getTime();
}
}
}
Existe algo mais simples, como alguma chamada de API que esqueci?
A conversão entre uma data / hora XML padrão e um objeto de data Java parece uma tarefa bastante rotineira e estou surpreso por ter que escrever este código.
Alguma sugestão?
NOTAS: Minhas classes JAXB são geradas automaticamente a partir de um esquema. O processo de construção em meu projeto não permite que eu faça alterações manuais nas classes geradas. Os elementos xs: dateTime estão sendo gerados por XJC como XMLGregorianCalendar nas classes JAXB. O esquema é estendido e ajustado periodicamente, portanto, tenho permissão para fazer alterações limitadas no arquivo XSD do esquema.
ATUALIZAÇÃO NA SOLUÇÃO: A solução proposta por Blaise me permitiu tirar XMLGregorianCalendar da mistura e lidar com objetos java.util.Calendar. Adicionando uma cláusula de ligação JAXB na parte superior do meu arquivo de esquema, o XJC é capaz de gerar mapeamentos mais apropriados para xs: dateTime em minhas classes JAXB. Aqui estão alguns trechos que mostram as modificações em meu arquivo XSD.
O elemento raiz no arquivo XSD:
<xs:schema xmlns:mydata="http://my.example.com/mydata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://my.example.com/mydata" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="0.2" xml:lang="en" jaxb:version="2.0">
Bloco de anotação de ligação JAXB, inserido imediatamente após o elemento raiz em XSD:
<xs:annotation>
<xs:appinfo>
<jaxb:globalBindings>
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" />
</jaxb:globalBindings>
</xs:appinfo>
</xs:annotation>
Como o campo XML xs: dateTime também armazena fuso horário, pode ser melhor para mim trabalhar com Calendário em vez de Data de qualquer maneira, já que os objetos Calendar têm uma API muito boa para trabalhar com localidades e fusos horários. Em qualquer caso, fico muito mais feliz em lidar com objetos Calendar em vez de XMLGregorianCalendar. Não há mais necessidade dos métodos de conversão que listei acima. Não cheguei até java.util.Date, mas perto o suficiente!
util
pacote e usá-lo.Respostas:
Por que não usar um arquivo de ligação externa para informar ao XJC para gerar campos java.util.Date em vez de XMLGregorianCalendar?
Consulte também Como mapeio xs: date para java.util.Date? Blog
fonte
De XMLGregorianCalendar a java.util.Date, você pode simplesmente fazer:
fonte
De java.util.Date a XMLGregorianCalendar, você pode simplesmente fazer:
Código editado após o primeiro comentário de @f-puras, por causa eu cometi um erro.
fonte
Tive de fazer algumas alterações para que funcionasse, pois algumas coisas parecem ter mudado nesse ínterim:
Aqui está um exemplo prático, espero que ajude (estou usando JodaTime, mas neste caso SimpleDate seria suficiente):
No xsd, segui as excelentes referências fornecidas acima, então incluí esta anotação xml:
fonte
Eu também tive esse tipo de dor de cabeça. Livrei-me dele simplesmente representando os campos de tempo como long primitivos no meu POJO. Agora, a geração do meu código de cliente WS lida com tudo corretamente e sem mais porcaria XML para Java. E, claro, lidar com millis no lado Java é simples e indolor. O princípio do KISS é demais!
fonte
Você pode usar esta personalização para alterar o mapeamento padrão para java.util.Date
fonte
Personalização do calendário e da data durante o Marshaling
Etapa 1: preparar o xml de ligação jaxb para propriedades personalizadas, neste caso eu preparei para data e calendário
Setp 2: Adicionar arquivo de ligação jaxb personalizado ao Apache ou qualquer plug-in relacionado na opção xsd como mencionado abaixo
Conjunto 3: escreva o código para a classe CalendarConverter
Conjunto 4: Saída
fonte