XMLGregorianCalendar için java.util.Date


601

Bir java.util.Date bir XMLGregorianCalendar almak için uygun bir yolu yok mu?


Bilginize: Bu korkunç sınıfların her ikisi de yıllar önce JSR 310'da tanımlanan java.time sınıflarıyla tamamlanmıştı. ZonedDateTimeSınıf ve eski sınıflara eklenen yeni dönüştürme yöntemleri konusuna bakın . Bu Cevapla Ayrıntılar Ole VV
Basil Bourque

Yanıtlar:


36

Bu 10 yıllık soruya geri adım atmak ve modern bir bakış atmak istiyorum. Bahsedilen sınıflar Dateve XMLGregorianCalendarşimdi eskidir. Bunların kullanımına meydan okuyorum ve alternatifler sunuyorum.

  • Dateher zaman kötü tasarlanmış ve 20 yıldan daha eski. Bu basit: kullanma.
  • XMLGregorianCalendarçok eskidir ve eski moda bir tasarıma sahiptir. Anladığım kadarıyla, XML belgeleri için XML formatında tarih ve saat üretmek için kullanıldı. Gibi 2009-05-07T19:05:45.678+02:00veya 2009-05-07T17:05:45.678Z. Bu formatlar, modern Java tarih ve saat API'sı olan java.time sınıflarının bunları tercih edebileceğimiz ISO 8601 ile yeterince uyumludur.

Dönüştürmeye gerek yok

Birçok (en?) Amaçlar için bir modern yerine bir Dateolacaktır Instant. An Instantzamandaki bir noktadır (aynen olduğu gibi Date).

    Instant yourInstant = // ...
    System.out.println(yourInstant);

Bu snippet'ten bir örnek çıktı:

2009-05-07T17: 05: 45.678Z

XMLGregorianCalendarYukarıdaki örnek dizelerimin ikincisi ile aynı . Çoğunuzun bildiği gibi, Instant.toStringdolaylı olarak çağrılmaktan gelir System.out.println. Java.time ile birçok durumda eski günlerdeki biz arasında yapılan bu dönüşümleri gerekmez Date, Calendar, XMLGregorianCalendarve diğer sınıflar (biz ihtiyaç dönüşümleri yapmak bazı durumlarda olsa, sana sonraki bölümde birkaç gösteriyorum) .

Ofseti kontrol etme

Ne Datene de ne Instantbir saat dilimi ne de UTC dengesi yoktur. Ben Noland'ın daha önce kabul edilmiş ve hala en yüksek oyu alan cevabı, JVM'lerin ofsetini seçmek için geçerli varsayılan saat dilimini kullanır XMLGregorianCalendar. Modern bir nesneye ofset eklemek için bir OffsetDateTime. Örneğin:

    ZoneId zone = ZoneId.of("America/Asuncion");
    OffsetDateTime dateTime = yourInstant.atZone(zone).toOffsetDateTime();
    System.out.println(dateTime);

2009-05-07T13: 05: 45,678-04: 00

Yine bu XML formatına uygundur. Tekrar geçerli JVM saat dilimi ayarını kullanmak istiyorsanız, set zoneiçin ZoneId.systemDefault().

Kesinlikle bir XMLGregorianCalendar gerekiyorsa ne olur?

Dönüştürmek Instantiçin daha fazla yol var XMLGregorianCalendar. Her biri artıları ve eksileri olan bir çift sunacağım. İlk olarak, tıpkı XMLGregorianCalendarbir dize ürettiği gibi 2009-05-07T17:05:45.678Z, böyle bir dizeden de oluşturulabilir:

    String dateTimeString = yourInstant.toString();
    XMLGregorianCalendar date2
            = DatatypeFactory.newInstance().newXMLGregorianCalendar(dateTimeString);
    System.out.println(date2);

2009-05-07T17: 05: 45.678Z

Pro: Kısa ve sürprizler olduğunu düşünmüyorum. Con: Bana göre, anı bir dizeye biçimlendiren ve onu ayrıştıran bir atık gibi geliyor.

    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

Pro: Bu resmi dönüşüm. Ofseti kontrol etmek doğal olarak gelir. Con: Daha fazla adım atıyor ve bu nedenle daha uzun.

Randevumuz varsa ne olur?

DateEski bir API'dan, şimdi değiştirmeyi göze alamayacağınız eski moda bir nesneniz varsa, şu biçime dönüştürün Instant:

    Instant i = yourDate.toInstant();
    System.out.println(i);

Çıktı öncekiyle aynı:

2009-05-07T17: 05: 45.678Z

Ofseti kontrol etmek istiyorsanız OffsetDateTime, yukarıdakiyle aynı şekilde daha ileriye dönüştürün .

Eski modaya sahipseniz Dateve kesinlikle eski modaya ihtiyacınız varsa XMLGregorianCalendar, Ben Noland'ın cevabını kullanın.

Bağlantılar


1034
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);

5
Bazı dönüştürücü sınıflarında getInstance () yöntemini statik bir değişken olarak saklamak kaydediliyor mu? JavaDoc'da aramaya çalıştım ama hiçbir şey bulamadım. Eşzamanlı kullanımda sorun olup olmayacağını bilmek biraz zor mu?
Martin

36
JodaTime'ı kullanmak istiyorsanız bunu tek bir satırda yapabilirsiniz: DatatypeFactory.newInstance (). NewXMLGregorianCalendar (new DateTime (). ToGregorianCalendar ())
Nicolas Mommaerts 15:13

3
XMLGregorianCalendar date2 = DatatypeFactory.newInstance (). NewXMLGregorianCalendar (yeni GregorianCalendar (YYYY, MM, DD));
Junchen Liu

3
Lütfen Takvim'in güvenli olmadığını ve bu nedenle GregorianCalender'ın olmadığını unutmayın. Ayrıca bkz. Stackoverflow.com/questions/12131324/…
anket

Bir satır sürümü - DatatypeFactory.newInstance (). NewXMLGregorianCalendar (new GregorianCalendar () {{setTime (yourDate);}})
Alex Vayda

205

Burada karşıt dönüşümü arayanlar için ( XMLGregorianCalendarila arasında Date):

XMLGregorianCalendar xcal = <assume this is initialized>;
java.util.Date dt = xcal.toGregorianCalendar().getTime();

31

İşte bir GregorianCalendar XMLGregorianCalendar dönüştürmek için bir yöntem; Bir java.util.Date'den GregorianCalendar'e dönüştürme işlemini sizin için bir egzersiz olarak bırakacağım:

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);
   }

}

DÜZENLEME: Slooow :-)


6
Bu soruda belirtilen değil GregorianCalendar XMLGregorianCalendar dönüştürmek için bir çözüm
ftrujillo


12

Yukarıdaki cevapları tam olarak karşılayamadığım için çözümümü aşağıya ekleyeceğimi düşündüm. Xml şemam, tek bir DateTime alanı değil, ayrı Tarih ve Saat öğelerini gerektiriyordu. Yukarıda kullanılan standart XMLGregorianCalendar yapıcısı bir DateTime alanı oluşturur

Ay'a bir tane eklemek zorunda gibi birkaç gothca var (java 0'dan ayları saydığı için).

GregorianCalendar cal = new GregorianCalendar();
cal.setTime(yourDate);
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendarDate(cal.get(Calendar.YEAR), cal.get(Calendar.MONTH)+1, cal.get(Calendar.DAY_OF_MONTH), 0);
XMLGregorianCalendar xmlTime = DatatypeFactory.newInstance().newXMLGregorianCalendarTime(cal.get(Calendar.HOUR_OF_DAY), cal.get(Calendar.MINUTE), cal.get(Calendar.SECOND), 0);

10

Ben burada kodlama doğru olduğunu umuyoruz; D Daha hızlı yapmak için sadece yapıcı çağrı yerine GregorianCalendar çirkin getInstance () çağrısı kullanın:

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 {
      // do not forget the type cast :/
      GregorianCalendar gcal = (GregorianCalendar) GregorianCalendar.getInstance();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

14
-1 .getInstance () kullanmak için. GregorianCalendar.getInstance()eşdeğeridir Calendar.getInstance(). Daha Calendar.getInstance()hızlı yapamaz, çünkü aynı kullanır new GregorianCalendar(), ancak aynı zamanda varsayılan yerel ayarı kontrol eder ve bunun yerine Japonca veya Budist takvimi oluşturabilir, bu yüzden bazı şanslı kullanıcılar için olacak ClassCastException!
kan

6

Xml kodunu JAXBçözdüğünüz veya kodladığınızı varsayarsak, dateTime bağlamasını tamamen değiştirmek ve şemadaki her tarih için `XMLGregorianCalendar 'dan başka bir şey kullanmak mümkündür.

Böylece JAXBdeğer veren müthiş bir kod yazmak için zaman harcayabilirsiniz tekrarlayan şeyler yapmak zorunda.

Bir jodatime örneği DateTime: (Bunu java.util.Date ile yapmak da işe yarayacaktır - ancak bazı sınırlamalar ile.

<jxb:globalBindings>
    <jxb:javaType name="org.joda.time.LocalDateTime" xmlType="xs:dateTime"
        parseMethod="test.util.JaxbConverter.parseDateTime"
        printMethod="se.seb.bis.test.util.JaxbConverter.printDateTime" />
    <jxb:javaType name="org.joda.time.LocalDate" xmlType="xs:date"
        parseMethod="test.util.JaxbConverter.parseDate"
        printMethod="test.util.JaxbConverter.printDate" />
    <jxb:javaType name="org.joda.time.LocalTime" xmlType="xs:time"
        parseMethod="test.util.JaxbConverter.parseTime"
        printMethod="test.util.JaxbConverter.printTime" />
    <jxb:serializable uid="2" />
</jxb:globalBindings>

Ve dönüştürücü:

public class JaxbConverter {
static final DateTimeFormatter dtf = ISODateTimeFormat.dateTimeNoMillis();
static final DateTimeFormatter df = ISODateTimeFormat.date();
static final DateTimeFormatter tf = ISODateTimeFormat.time();

public static LocalDateTime parseDateTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        LocalDateTime r = dtf.parseLocalDateTime(s);
        return r;
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDateTime(LocalDateTime d) {
    try {
        if (d == null)
            return null;
        return dtf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalDate parseDate(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalDate(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printDate(LocalDate d) {
    try {
        if (d == null)
            return null;
        return df.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static String printTime(LocalTime d) {
    try {
        if (d == null)
            return null;
        return tf.print(d);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

public static LocalTime parseTime(String s) {
    try {
        if (StringUtils.trimToEmpty(s).isEmpty())
            return null;
        return df.parseLocalTime(s);
    } catch (Exception e) {
        throw new IllegalArgumentException(e);
    }
}

Buraya bakın: XmlGregorianCalendar'ı tarihe göre nasıl değiştirebilirim?

Saat dilimi + zaman damgasına dayalı bir anı eşlemekten mutluluk duyuyorsanız ve orijinal saat dilimi gerçekten alakalı değilse java.util.Date, muhtemelen de iyidir.


0

Bu kodu inceleyin: -

/* Create Date Object */
Date date = new Date();
XMLGregorianCalendar xmlDate = null;
GregorianCalendar gc = new GregorianCalendar();

gc.setTime(date);

try{
    xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc);
}
catch(Exception e){
    e.printStackTrace();
}

System.out.println("XMLGregorianCalendar :- " + xmlDate);

Tüm örneği burada görebilirsiniz


Bu cevabın yeni bir şey sağlamadığını düşünmüyorum .. Belki de bir önceki cevabı hemen hemen aynı başka bir cevap göndermek yerine düzenleyebilirsiniz.
kış

1
XMLGregorianCalendar için dateFormat nasıl yapılır?
Panadol Chong
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.