java.util.Date to XMLGregorianCalWiki


601

Không có cách nào thuận tiện để nhận từ java.util.Date sang XMLGregorianCalWiki?


FYI: Cả hai lớp khủng khiếp này đã được thay thế từ nhiều năm trước bởi các lớp java.time được định nghĩa trong JSR 310. Xem ZonedDateTimelớp và các phương thức chuyển đổi mới được thêm vào các lớp kế thừa. Chi tiết trong câu trả lời này của Ole VV
Basil Bourque

Câu trả lời:


36

Tôi muốn lùi lại một bước và một cái nhìn hiện đại về câu hỏi 10 năm tuổi này. Các lớp được đề cập, DateXMLGregorianCalendar, bây giờ đã cũ. Tôi thách thức việc sử dụng chúng và đưa ra giải pháp thay thế.

  • Dateluôn được thiết kế kém và đã hơn 20 tuổi. Điều này rất đơn giản: không sử dụng nó.
  • XMLGregorianCalendarcũng cũ và có một thiết kế lỗi thời. Theo tôi hiểu, nó được sử dụng để tạo ngày và giờ theo định dạng XML cho các tài liệu XML. Thích 2009-05-07T19:05:45.678+02:00hay 2009-05-07T17:05:45.678Z. Các định dạng này đủ phù hợp với ISO 8601 rằng các lớp của java.time, API ngày và giờ Java hiện đại, có thể tạo ra chúng, mà chúng tôi thích.

Không cần chuyển đổi

Đối với nhiều mục đích (hầu hết?), Sự thay thế hiện đại cho một Datesẽ là một Instant. An Instantlà một điểm trong thời gian (giống như một Date).

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

Một ví dụ đầu ra từ đoạn trích này:

2009-05-07T17: 05: 45.678Z

Nó giống như chuỗi sau của ví dụ của tôi XMLGregorianCalendarở trên. Như hầu hết các bạn đều biết, nó xuất phát từ Instant.toStringviệc được gọi ngầm System.out.println. Với java.time, trong nhiều trường hợp chúng ta không cần chuyển đổi mà trong những ngày cũ, chúng tôi thực hiện giữa Date, Calendar, XMLGregorianCalendarvà các lớp khác (trong một số trường hợp chúng tôi làm chuyển đổi cần thiết, tuy nhiên, tôi đang hiển thị cho bạn một vài trong phần tiếp theo) .

Kiểm soát bù

Không Datephải cũng không Instantcó múi giờ hay bù UTC. Câu trả lời được chấp nhận trước đây và vẫn được bình chọn cao nhất bởi Ben Noland sử dụng múi giờ mặc định hiện tại của JVM để chọn phần bù của XMLGregorianCalendar. Để bao gồm một phần bù trong một đối tượng hiện đại, chúng ta sử dụng một OffsetDateTime. Ví dụ:

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

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

Một lần nữa điều này phù hợp với định dạng XML. Nếu bạn muốn sử dụng lại cài đặt múi giờ JVM hiện tại, hãy đặt zonethành ZoneId.systemDefault().

Điều gì xảy ra nếu tôi thực sự cần một XMLGregorianCalWiki?

Có nhiều cách để chuyển đổi Instantsang XMLGregorianCalendar. Tôi sẽ trình bày một cặp vợ chồng, mỗi người có ưu và nhược điểm của nó. Đầu tiên, giống như XMLGregorianCalendarmột chuỗi tạo ra 2009-05-07T17:05:45.678Z, nó cũng có thể được xây dựng từ một chuỗi như vậy:

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

2009-05-07T17: 05: 45.678Z

Pro: nó ngắn và tôi không nghĩ nó mang lại bất ngờ nào. Con: Đối với tôi, nó giống như một sự lãng phí định dạng tức thời thành một chuỗi và phân tích lại nó.

    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: Đây là chuyển đổi chính thức. Kiểm soát bù đến một cách tự nhiên. Con: Nó trải qua nhiều bước hơn và do đó dài hơn.

Nếu chúng ta có một ngày thì sao?

Nếu bạn có một Dateđối tượng lỗi thời từ API kế thừa mà bạn không thể đủ khả năng để thay đổi ngay bây giờ, hãy chuyển đổi nó thành Instant:

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

Đầu ra giống như trước:

2009-05-07T17: 05: 45.678Z

Nếu bạn muốn kiểm soát phần bù, hãy chuyển đổi thành một OffsetDateTimecách tương tự như trên.

Nếu bạn đã có một kiểu cũ Datevà hoàn toàn cần một kiểu cũ XMLGregorianCalendar, chỉ cần sử dụng câu trả lời của Ben Noland.

Liên kết


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

5
Có lưu để giữ getInstance () làm biến tĩnh trong một số lớp chuyển đổi không? Tôi đã cố gắng tìm kiếm nó trong JavaDoc nhưng không thể tìm thấy gì. Kinda khó để biết nếu có vấn đề trong việc sử dụng đồng thời?
Martin

36
Nếu bạn sẵn sàng để sử dụng JodaTime bạn có thể làm điều này trong một dòng: DatatypeFactory.newInstance () newXMLGregorianCalendar. (DateTime mới () toGregorianCalendar ().)
Nicolas Mommaerts

3
XMLGregorianCalWiki date2 = DatatypeFactory.newInstance (). NewXMLGregorianCalWiki (new GregorianCalWiki (YYYY, MM, DD));
Junchen Liu

3
Xin lưu ý rằng Lịch không phải là chủ đề an toàn và do đó GregorianCalender cũng không. Xem thêm stackoverflow.com/questions/12131324/
câu hỏi

Phiên bản một dòng - DatatypeFactory.newInstance (). NewXMLGregorianCalWiki (new GregorianCalWiki () {{setTime (yourDate);}})
Alex Vayda

205

Đối với những người có thể kết thúc ở đây, tìm kiếm chuyển đổi ngược lại (từ XMLGregorianCalendarđến Date):

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

31

Đây là một phương pháp để chuyển đổi từ GregorianCalWiki sang XMLGregorianCalWiki; Tôi sẽ để lại phần chuyển đổi từ java.util.Date sang GregorianCalWiki như một bài tập cho bạ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 {
      GregorianCalendar gcal = new GregorianCalendar();
      XMLGregorianCalendar xgcal = DatatypeFactory.newInstance()
            .newXMLGregorianCalendar(gcal);
      System.out.println(xgcal);
   }

}

EDIT: Slooow :-)


6
Đây là một giải pháp để chuyển đổi GregorianCalWiki thành XMLGregorianCalWiki và không phải là những gì được chỉ ra trong câu hỏi
ftrujillo


12

Chỉ cần nghĩ rằng tôi sẽ thêm giải pháp của mình bên dưới, vì các câu trả lời ở trên không đáp ứng được nhu cầu chính xác của tôi. Lược đồ Xml của tôi yêu cầu tách biệt các yếu tố Ngày và Giờ, không phải là trường DateTime đơn lẻ. Trình xây dựng XMLGregorianCalWiki tiêu chuẩn được sử dụng ở trên sẽ tạo ra trường DateTime

Lưu ý rằng có một vài gothca, chẳng hạn như phải thêm một vào tháng (vì java tính từ 0 tháng).

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

Tôi hy vọng mã hóa của tôi ở đây là đúng; D Để làm cho nó nhanh hơn, chỉ cần sử dụng lệnh gọi getInstance () xấu xí của GregorianCalWiki thay vì gọi hàm tạo:

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 để sử dụng .getInstance (). GregorianCalendar.getInstance()là tương đương với Calendar.getInstance(). Không Calendar.getInstance()thể làm cho nó nhanh hơn, bởi vì nó sử dụng tương tự new GregorianCalendar(), nhưng trước đó nó cũng kiểm tra ngôn ngữ mặc định và có thể tạo lịch Nhật Bản hoặc Buddish, vì vậy đối với một số người dùng may mắn thì sẽ như ClassCastExceptionvậy!
kan

6

Giả sử bạn đang giải mã hoặc mã hóa xml và sử dụng JAXB, thì có thể thay thế hoàn toàn ràng buộc dateTime và sử dụng một cái gì đó khác hơn `XMLGregorianCalWiki 'cho mỗi ngày trong lược đồ.

Theo cách đó bạn có thể có JAXB thực hiện các công cụ lặp đi lặp lại trong khi bạn có thể dành thời gian để viết mã tuyệt vời mang lại giá trị.

Ví dụ cho jodatime DateTime: (Làm điều này với java.util.Date cũng sẽ hoạt động - nhưng với một số hạn chế nhất định. Tôi thích jodatime và nó được sao chép từ mã của tôi để tôi biết nó hoạt động ...)

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

Và bộ chuyển đổi:

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

Xem ở đây: làm thế nào để thay thế XmlGregorianCalWiki theo ngày?

Nếu bạn hài lòng khi chỉ ánh xạ tới tức thời dựa trên múi giờ + dấu thời gian và múi giờ ban đầu không thực sự phù hợp, thì java.util.Datecó lẽ cũng tốt.


0

Kiểm tra mã này: -

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

Bạn có thể xem ví dụ đầy đủ ở đây


Tôi không nghĩ rằng câu trả lời này không cung cấp gì mới .. Có lẽ bạn có thể chỉnh sửa câu trả lời trước đó thay vì đăng một câu khác gần như giống nhau.
mùa đông

1
Làm cách nào để tạo một dateFormat cho XMLGregorianCalWiki?
Panadol Chong
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.