답변:
이 10 살짜리 질문에 대해 한 걸음 물러나 현대적인 모습을보고 싶습니다. 언급 된 클래스 Date
및 XMLGregorianCalendar
은 (는) 현재는 오래되었습니다. 나는 그것들의 사용에 도전하고 대안을 제공합니다.
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을 사용하면 많은 경우에 우리는 이전 Date
에 Calendar
, 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 시간대 설정을 사용하려면, 설정 zone
에ZoneId.systemDefault()
.
로 변환 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
있고 구식이 절대적으로 필요한 경우 XMLGregorianCalendar
Ben Noland의 답변을 사용하십시오.
GregorianCalendar c = new GregorianCalendar();
c.setTime(yourDate);
XMLGregorianCalendar date2 = DatatypeFactory.newInstance().newXMLGregorianCalendar(c);
다음은 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 :-)
위의 답변이 정확한 요구를 충족시키지 못했기 때문에 아래에 솔루션을 추가한다고 생각했습니다. 내 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);
}
}
GregorianCalendar.getInstance()
와 같습니다 Calendar.getInstance()
. 는 동일한를 Calendar.getInstance()
사용하기 때문에 더 빨리 만들 수 없지만 new GregorianCalendar()
기본 로케일을 확인하기 전에 대신 일본어 또는 Buddish 달력을 만들 수 있으므로 운이 좋은 사용자에게는 더 빠릅니다 ClassCastException
!
xml을 디코딩하거나 인코딩하고을 사용한다고 가정하면 JAXB
dateTime 바인딩을 완전히 바꾸고 스키마의 모든 날짜에 대해 '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
에도 괜찮을 것입니다.
이 코드를 확인하십시오 :-
/* 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);
여기에서 완전한 예를 볼 수 있습니다
ZonedDateTime
클래스 및 레거시 클래스에 추가 된 새 변환 메소드를 참조하십시오 . 이 답변의 세부 정보 Ole VV