java.util.Date에 XMLGregorianCalendar


601

java.util.Date에서 XMLGregorianCalendar로 이동하는 편리한 방법이 없습니까?


참고 :이 두 가지 끔찍한 클래스는 몇 년 전에 JSR 310에 정의 된 java.time 클래스로 대체되었습니다. ZonedDateTime클래스 및 레거시 클래스에 추가 된 새 변환 메소드를 참조하십시오 . 이 답변의 세부 정보 Ole VV
Basil Bourque

답변:


36

이 10 살짜리 질문에 대해 한 걸음 물러나 현대적인 모습을보고 싶습니다. 언급 된 클래스 DateXMLGregorianCalendar은 (는) 현재는 오래되었습니다. 나는 그것들의 사용에 도전하고 대안을 제공합니다.

  • Date항상 제대로 설계되지 않았으며 20 세 이상입니다. 이것은 간단합니다. 사용하지 마십시오.
  • XMLGregorianCalendar구식이며 구식 디자인입니다. 내가 이해하는 것처럼 XML 문서의 날짜 및 시간을 XML 형식으로 생성하는 데 사용되었습니다. 2009-05-07T19:05:45.678+02:00또는 처럼 2009-05-07T17:05:45.678Z. 이러한 형식은 최신 Java 날짜 및 시간 API 인 java.time 클래스가이를 작성할 수 있다는 점에서 ISO 8601과 충분히 일치합니다.

변환이 필요하지 않습니다

많은 (대부분의) 목적을 위해 현대적인 Date의지 대체는 의지 Instant입니다. An Instant은 특정 시점입니다 (있는 그대로 Date).

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

이 스 니펫의 출력 예는 다음과 같습니다.

2009-05-07T17 : 05 : 45.678Z

XMLGregorianCalendar위의 예제 문자열 후자와 같습니다 . 대부분의 사람들이 알고 있듯이,은 (는)에 Instant.toString의해 암시 적으로 호출됩니다 System.out.println. java.time을 사용하면 많은 경우에 우리는 이전 DateCalendar, XMLGregorianCalendar및 다른 클래스 사이 에서 만든 변환이 필요하지 않습니다 (어떤 경우에는 변환이 필요하지만 다음 섹션에서 몇 가지를 보여줍니다) .

오프셋 제어

a Date또는 in Instant에는 시간대 나 UTC 오프셋이 없습니다. Ben Noland가 이전에 수락했지만 여전히 가장 높은 투표 응답은 JVM의 현재 기본 시간대를 사용하여의 오프셋을 선택합니다 XMLGregorianCalendar. 현대 객체에 오프셋을 포함시키기 위해 OffsetDateTime. 예를 들면 다음과 같습니다.

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

2009-05-07T13 : 05 : 45.678-04 : 00

이 역시 XML 형식을 따릅니다. 다시 현재의 JVM 시간대 설정을 사용하려면, 설정 zoneZoneId.systemDefault() .

XMLGregorianCalendar가 절대적으로 필요한 경우 어떻게합니까?

로 변환 Instant하는 더 많은 방법이 있습니다 XMLGregorianCalendar. 나는 장단점이있는 부부를 선물 할 것입니다. 먼저, XMLGregorianCalendar과 같은 문자열을 생성하는 것처럼 2009-05-07T17:05:45.678Z이러한 문자열로도 작성할 수 있습니다.

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

2009-05-07T17 : 05 : 45.678Z

프로 : 짧고 놀랍지 않다고 생각합니다. 단점 : 즉석에서 문자열을 형식화하고 다시 구문 분석하는 것은 낭비처럼 느껴집니다.

    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

프로 : 공식적인 전환입니다. 오프셋 제어는 자연스럽게 이루어집니다. 단점 : 더 많은 단계를 거치므로 더 길어집니다.

데이트를하면 어떻게 되나요?

Date기존 API에서 구식 객체를 가져 와서 지금 당장 변경할 수 없다면 다음으로 변환하십시오 Instant.

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

출력은 이전과 동일합니다.

2009-05-07T17 : 05 : 45.678Z

오프셋을 제어하려면 OffsetDateTime위와 동일한 방식으로 추가로 변환 하십시오.

구식이 Date있고 구식이 절대적으로 필요한 경우 XMLGregorianCalendarBen Noland의 답변을 사용하십시오.

연결


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

5
getInstance ()를 일부 변환기 클래스에서 정적 변수로 유지하기 위해 저장됩니까? JavaDoc에서 찾아 보았지만 아무것도 찾을 수 없었습니다. 동시 사용에 문제가 있는지 알기가 어렵습니까?
Martin

36
JodaTime을 기꺼이 사용하려는 경우 한 줄로 수행 할 수 있습니다. DatatypeFactory.newInstance (). newXMLGregorianCalendar (new DateTime (). toGregorianCalendar ())
Nicolas Mommaerts

3
XMLGregorianCalendar date2 = DatatypeFactory.newInstance (). newXMLGregorianCalendar (새로운 GregorianCalendar (YYYY, MM, DD));
Junchen Liu

3
캘린더는 스레드 안전하지 않으므로 GregorianCalender도 스레드가 안전하지 않습니다. 또한 참조 stackoverflow.com/questions/12131324/...
questionaire

한 줄 버전-DatatypeFactory.newInstance (). newXMLGregorianCalendar (new GregorianCalendar () {{setTime (yourDate);}})
Alex Vayda 2016 년

205

여기에서 반대 변환을 찾고있는 사람들에게는 (에서 XMLGregorianCalendar~로 Date) :

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

31

다음은 GregorianCalendar에서 XMLGregorianCalendar로 변환하는 방법입니다. java.util.Date에서 GregorianCalendar로 변환하는 부분을 연습으로 남겨 두겠습니다.

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

}

편집 : Slooow :-)


6
이것은 GregorianCalendar를 XMLGregorianCalendar로 변환하고 질문에 표시된 내용이 아닌 솔루션
ftrujillo


12

위의 답변이 정확한 요구를 충족시키지 못했기 때문에 아래에 솔루션을 추가한다고 생각했습니다. 내 Xml 스키마에는 단일 DateTime 필드가 아닌 별도의 Date 및 Time 요소가 필요했습니다. 위에서 사용 된 표준 XMLGregorianCalendar 생성자는 DateTime 필드를 생성합니다.

한 달에 1을 추가 해야하는 것과 같은 두 가지 고트 카가 있음에 유의하십시오 (Java는 0에서 개월을 계산하므로).

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

여기에 내 인코딩이 옳았기를 바랍니다 .D 더 빨리 만들려면 생성자 호출 대신 GregorianCalendar의 못생긴 getInstance () 호출을 사용하십시오.

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
.getInstance ()를 사용하는 경우 -1입니다. GregorianCalendar.getInstance()와 같습니다 Calendar.getInstance(). 는 동일한를 Calendar.getInstance()사용하기 때문에 더 빨리 만들 수 없지만 new GregorianCalendar()기본 로케일을 확인하기 전에 대신 일본어 또는 Buddish 달력을 만들 수 있으므로 운이 좋은 사용자에게는 더 빠릅니다 ClassCastException!
kan

6

xml을 디코딩하거나 인코딩하고을 사용한다고 가정하면 JAXBdateTime 바인딩을 완전히 바꾸고 스키마의 모든 날짜에 대해 'XMLGregorianCalendar'이외의 것을 사용할 수 있습니다.

그런 식으로 당신은 할 수 있습니다 JAXB 반복적 인 작업을 수행하면서 가치를 제공하는 멋진 코드를 작성하는 데 시간을 할애 할 수 있습니다.

jodatime의 예 DateTime: (java.util.Date를 사용 하여이 작업을 수행해 도 작동하지만 특정 제한이 있습니다. jodatime을 선호하며 코드에서 복사되어 작동한다는 것을 알고 있습니다 ...)

<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>

그리고 변환기 :

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

여기를 참조하십시오 : 어떻게 XmlGregorianCalendar를 날짜로 대체합니까?

시간대 + 타임 스탬프를 기준으로 인스턴트에 매핑하고 원래 시간대가 실제로 관련이없는 경우 java.util.Date에도 괜찮을 것입니다.


0

이 코드를 확인하십시오 :-

/* 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);

여기에서 완전한 예를 볼 수 있습니다


이 답변이 새로운 것을 제공한다고 생각하지 않습니다. 아마도 다른 답변을 거의 똑같이 게시하는 대신 이전 답변을 편집 할 수 있습니다.
겨울

1
XMLGregorianCalendar에 대해 dateFormat을 수행하는 방법은 무엇입니까?
Panadol Chong
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.