FYI: Essas duas classes terríveis foram substituídas anos atrás pelas classes java.time definidas no JSR 310. Consulte a ZonedDateTimeclasse e novos métodos de conversão adicionados às classes herdadas. Detalhes nesta resposta por Ole VV
Basil Bourque
Respostas:
36
Gostaria de dar um passo atrás e dar uma olhada moderna nesta questão de 10 anos de idade. As aulas mencionadas Datee XMLGregorianCalendarsão antigas agora. Desafio o uso deles e ofereço alternativas.
Datesempre foi mal projetado e tem mais de 20 anos. Isso é simples: não use.
XMLGregorianCalendartambém é antigo e tem um design antiquado. Pelo que entendi, foi usado para produzir datas e horas no formato XML para documentos XML. Como 2009-05-07T19:05:45.678+02:00ou 2009-05-07T17:05:45.678Z. Esses formatos concordam bastante com a ISO 8601 para que as classes de java.time, a moderna API de data e hora de Java, possam produzi-las, como preferimos.
Nenhuma conversão necessária
Para muitos propósitos (a maioria?), A substituição moderna de a Dateserá um Instant. An Instanté um ponto no tempo (exatamente como Dateé).
É o mesmo que o último dos meus exemplos de XMLGregorianCalendarstrings acima. Como muitos de vocês sabem, vem de Instant.toStringser implicitamente chamado por System.out.println. Com java.time, em muitos casos, não precisamos das conversões que nos velhos tempos que fizemos entre Date, Calendar, XMLGregorianCalendare outras classes (em alguns casos, fazer conversões necessidade, porém, eu estou mostrando-lhe um par na próxima seção) .
Controlando o deslocamento
Nem a Datenem in Instantpossui um fuso horário nem um deslocamento UTC. A resposta anteriormente aceita e ainda mais votada por Ben Noland usa o fuso horário padrão atual da JVMs para selecionar o deslocamento da XMLGregorianCalendar. Para incluir um deslocamento em um objeto moderno, usamos um OffsetDateTime. Por exemplo:
ZoneId zone =ZoneId.of("America/Asuncion");OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();System.out.println(dateTime);
2009-05-07T13: 05: 45.678-04: 00
Novamente, isso está em conformidade com o formato XML. Se você deseja usar a configuração atual do fuso horário da JVM novamente, defina zonecomo ZoneId.systemDefault().
E se eu precisar absolutamente de um XMLGregorianCalendar?
Existem mais maneiras de converter Instantpara XMLGregorianCalendar. Vou apresentar um casal, cada um com seus prós e contras. Primeiro, assim como um XMLGregorianCalendarproduz uma string como 2009-05-07T17:05:45.678Z, também pode ser construído a partir dessa string:
É salvo manter o getInstance () como uma variável estática em alguma classe de conversor? Eu tentei procurar no JavaDoc, mas não consegui encontrar nada. Meio difícil saber se haverá problemas no uso simultâneo?
Martin
36
Se você estiver disposto a usar JodaTime você pode fazer isso em uma linha: DatatypeFactory.newInstance () newXMLGregorianCalendar. (New DateTime () toGregorianCalendar ().)
Esteja ciente de que o Calendário não é seguro para threads e, portanto, também não é GregorianCalender. Veja também stackoverflow.com/questions/12131324/…
questionaire
. Uma versão de linha - DatatypeFactory.newInstance () newXMLGregorianCalendar (novo GregorianCalendar () {{setTime (yourDate);}})
Alex Vayda
205
Para aqueles que podem acabar aqui procurando a conversão oposta (de XMLGregorianCalendarpara Date):
Aqui está um método para converter de um GregorianCalendar para XMLGregorianCalendar; Vou deixar a parte da conversão de um java.util.Date para o GregorianCalendar como um exercício para você:
Apenas pensei em adicionar minha solução abaixo, pois as respostas acima não atendiam às minhas necessidades exatas. Meu esquema Xml exigia elementos separados de Data e Hora, não um único campo DateTime. O construtor XMLGregorianCalendar padrão usado acima gerará um campo DateTime
Observe alguns gothca's, como adicionar um ao mês (já que o java conta meses a partir de 0).
Espero que minha codificação aqui esteja correta; D Para torná-lo mais rápido, use a chamada feia getInstance () do GregorianCalendar em vez da chamada do construtor:
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()é o equivalente de Calendar.getInstance(). O Calendar.getInstance()não pode torná-lo mais rápido, porque usa o mesmo new GregorianCalendar(), mas antes também verifica o código do idioma padrão e pode criar um calendário japonês ou budista; portanto, para alguns usuários sortudos, será ClassCastException!
kan
6
Supondo que você esteja decodificando ou codificando xml e usando JAXB, é possível substituir completamente a ligação dateTime e usar algo diferente de `XMLGregorianCalendar 'para todas as datas no esquema.
Dessa forma, você pode JAXBfazer coisas repetitivas enquanto pode gastar tempo escrevendo códigos incríveis que agregam valor.
Exemplo para um jodatime DateTime: (Fazer isso com o java.util.Date também funcionaria - mas com algumas limitações. Prefiro o jodatime e ele é copiado do meu código para que eu saiba que funciona ...)
Se você deseja apenas mapear para um instante com base no fuso horário + no registro de data e hora, e o fuso horário original não for realmente relevante, java.util.Dateprovavelmente também será bom.
ZonedDateTime
classe e novos métodos de conversão adicionados às classes herdadas. Detalhes nesta resposta por Ole VVRespostas:
Gostaria de dar um passo atrás e dar uma olhada moderna nesta questão de 10 anos de idade. As aulas mencionadas
Date
eXMLGregorianCalendar
são antigas agora. Desafio o uso deles e ofereço alternativas.Date
sempre foi mal projetado e tem mais de 20 anos. Isso é simples: não use.XMLGregorianCalendar
também é antigo e tem um design antiquado. Pelo que entendi, foi usado para produzir datas e horas no formato XML para documentos XML. Como2009-05-07T19:05:45.678+02:00
ou2009-05-07T17:05:45.678Z
. Esses formatos concordam bastante com a ISO 8601 para que as classes de java.time, a moderna API de data e hora de Java, possam produzi-las, como preferimos.Nenhuma conversão necessária
Para muitos propósitos (a maioria?), A substituição moderna de a
Date
será umInstant
. AnInstant
é um ponto no tempo (exatamente comoDate
é).Um exemplo de saída deste snippet:
É o mesmo que o último dos meus exemplos de
XMLGregorianCalendar
strings acima. Como muitos de vocês sabem, vem deInstant.toString
ser implicitamente chamado porSystem.out.println
. Com java.time, em muitos casos, não precisamos das conversões que nos velhos tempos que fizemos entreDate
,Calendar
,XMLGregorianCalendar
e outras classes (em alguns casos, fazer conversões necessidade, porém, eu estou mostrando-lhe um par na próxima seção) .Controlando o deslocamento
Nem a
Date
nem inInstant
possui um fuso horário nem um deslocamento UTC. A resposta anteriormente aceita e ainda mais votada por Ben Noland usa o fuso horário padrão atual da JVMs para selecionar o deslocamento daXMLGregorianCalendar
. Para incluir um deslocamento em um objeto moderno, usamos umOffsetDateTime
. Por exemplo:Novamente, isso está em conformidade com o formato XML. Se você deseja usar a configuração atual do fuso horário da JVM novamente, defina
zone
comoZoneId.systemDefault()
.E se eu precisar absolutamente de um XMLGregorianCalendar?
Existem mais maneiras de converter
Instant
paraXMLGregorianCalendar
. Vou apresentar um casal, cada um com seus prós e contras. Primeiro, assim como umXMLGregorianCalendar
produz uma string como2009-05-07T17:05:45.678Z
, também pode ser construído a partir dessa string:Pro: é curto e acho que não dá nenhuma surpresa. Contras: Para mim, parece um desperdício formatar o instante em uma sequência e analisá-la novamente.
Pro: É a conversão oficial. Controlar o deslocamento ocorre naturalmente. Con: Ele passa por mais etapas e, portanto, é mais longo.
E se tivermos um encontro?
Se você obteve um
Date
objeto antiquado de uma API herdada que não pode mudar agora, converta-o paraInstant
:A saída é a mesma de antes:
Se você deseja controlar o deslocamento, converta mais para um
OffsetDateTime
da mesma maneira que acima.Se você tem um antiquado
Date
e absolutamente precisa de um antiquadoXMLGregorianCalendar
, basta usar a resposta de Ben Noland.Ligações
fonte
fonte
Para aqueles que podem acabar aqui procurando a conversão oposta (de
XMLGregorianCalendar
paraDate
):fonte
Aqui está um método para converter de um GregorianCalendar para XMLGregorianCalendar; Vou deixar a parte da conversão de um java.util.Date para o GregorianCalendar como um exercício para você:
EDIT: Slooow :-)
fonte
Um exemplo de uma linha usando a biblioteca Joda-Time :
Agradecemos a Nicolas Mommaerts por seu comentário na resposta aceita .
fonte
Apenas pensei em adicionar minha solução abaixo, pois as respostas acima não atendiam às minhas necessidades exatas. Meu esquema Xml exigia elementos separados de Data e Hora, não um único campo DateTime. O construtor XMLGregorianCalendar padrão usado acima gerará um campo DateTime
Observe alguns gothca's, como adicionar um ao mês (já que o java conta meses a partir de 0).
fonte
Espero que minha codificação aqui esteja correta; D Para torná-lo mais rápido, use a chamada feia getInstance () do GregorianCalendar em vez da chamada do construtor:
fonte
GregorianCalendar.getInstance()
é o equivalente deCalendar.getInstance()
. OCalendar.getInstance()
não pode torná-lo mais rápido, porque usa o mesmonew GregorianCalendar()
, mas antes também verifica o código do idioma padrão e pode criar um calendário japonês ou budista; portanto, para alguns usuários sortudos, seráClassCastException
!Supondo que você esteja decodificando ou codificando xml e usando
JAXB
, é possível substituir completamente a ligação dateTime e usar algo diferente de `XMLGregorianCalendar 'para todas as datas no esquema.Dessa forma, você pode
JAXB
fazer coisas repetitivas enquanto pode gastar tempo escrevendo códigos incríveis que agregam valor.Exemplo para um jodatime
DateTime
: (Fazer isso com o java.util.Date também funcionaria - mas com algumas limitações. Prefiro o jodatime e ele é copiado do meu código para que eu saiba que funciona ...)E o conversor:
Veja aqui: como substituir o XmlGregorianCalendar por Data?
Se você deseja apenas mapear para um instante com base no fuso horário + no registro de data e hora, e o fuso horário original não for realmente relevante,
java.util.Date
provavelmente também será bom.fonte
Confira este código: -
Você pode ver um exemplo completo aqui
fonte