[java] java.util.Date에 XMLGregorianCalendar

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



답변

이 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의 답변을 사용하십시오.

연결


답변

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


답변

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

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


답변

다음은 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 🙂


답변

Joda-Time 라이브러리 를 사용하는 한 줄 예 :

XMLGregorianCalendar xgc = DatatypeFactory.newInstance().newXMLGregorianCalendar(new DateTime().toGregorianCalendar());

허용 된 답변대한 그의 의견에서 Nicolas Mommaerts 에게 감사드립니다 .


답변

위의 답변이 정확한 요구를 충족시키지 못했기 때문에 아래에 솔루션을 추가한다고 생각했습니다. 내 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);


답변

여기에 내 인코딩이 옳았기를 바랍니다 .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);
   }

}