2010-09-09 35 views
106

Tôi đang tìm một phương thức chuyển đổi đơn giản giữa java.util.Date và javax.xml.datatype.XMLGregorianCalendar theo cả hai hướng.Chuyển đổi đơn giản giữa java.util.Date và XMLGregorianCalendar

Đây là mã mà tôi đang sử dụng hiện nay:

import java.util.GregorianCalendar; 
import javax.xml.datatype.DatatypeConfigurationException; 
import javax.xml.datatype.DatatypeFactory; 
import javax.xml.datatype.XMLGregorianCalendar; 

/** 
* Utility class for converting between XMLGregorianCalendar and java.util.Date 
*/ 
public class XMLGregorianCalendarConverter { 

    /** 
    * Needed to create XMLGregorianCalendar instances 
    */ 
    private static DatatypeFactory df = null; 
    static { 
     try { 
      df = DatatypeFactory.newInstance(); 
     } catch (DatatypeConfigurationException dce) { 
      throw new IllegalStateException(
       "Exception while obtaining DatatypeFactory instance", dce); 
     } 
    } 

    /** 
    * Converts a java.util.Date into an instance of XMLGregorianCalendar 
    * 
    * @param date Instance of java.util.Date or a null reference 
    * @return XMLGregorianCalendar instance whose value is based upon the 
    * value in the date parameter. If the date parameter is null then 
    * this method will simply return null. 
    */ 
    public static XMLGregorianCalendar asXMLGregorianCalendar(java.util.Date date) { 
     if (date == null) { 
      return null; 
     } else { 
      GregorianCalendar gc = new GregorianCalendar(); 
      gc.setTimeInMillis(date.getTime()); 
      return df.newXMLGregorianCalendar(gc); 
     } 
    } 

    /** 
    * Converts an XMLGregorianCalendar to an instance of java.util.Date 
    * 
    * @param xgc Instance of XMLGregorianCalendar or a null reference 
    * @return java.util.Date instance whose value is based upon the 
    * value in the xgc parameter. If the xgc parameter is null then 
    * this method will simply return null. 
    */ 
    public static java.util.Date asDate(XMLGregorianCalendar xgc) { 
     if (xgc == null) { 
      return null; 
     } else { 
      return xgc.toGregorianCalendar().getTime(); 
     } 
    } 
} 

Có điều gì đơn giản hơn, giống như một số cuộc gọi API mà tôi đã bỏ qua?

Chuyển đổi giữa ngày/giờ XML chuẩn và đối tượng ngày Java có vẻ như một công việc khá thường xuyên và tôi ngạc nhiên là tôi phải viết mã này.

Mọi đề xuất?

GHI CHÚ: Các lớp JAXB của tôi được tự động tạo từ giản đồ. Quá trình xây dựng trên dự án của tôi không cho phép tôi thực hiện các thay đổi thủ công đối với các lớp được tạo ra. Các phần tử xs: dateTime đang được tạo bởi XJC dưới dạng XMLGregorianCalendar trong các lớp JAXB. Giản đồ này được mở rộng và điều chỉnh định kỳ, vì vậy tôi được phép thực hiện các thay đổi hạn chế đối với tệp XSD lược đồ.

CẬP NHẬT VỀ GIẢI PHÁP: Các giải pháp của Blaise đề xuất đã cho phép tôi đưa XMLGregorianCalendar ra khỏi hỗn hợp và đối phó với java.util.Calendar đối tượng để thay thế. Bằng cách thêm một mệnh đề liên kết JAXB ở đầu tệp lược đồ của tôi, XJC có thể tạo ra các ánh xạ thích hợp hơn cho xs: dateTime trong các lớp JAXB của tôi. Dưới đây là một số đoạn trích hiển thị các sửa đổi trong tệp XSD của tôi.

Phần tử gốc trong file XSD:

<xs:schema xmlns:mydata="http://my.example.com/mydata" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" targetNamespace="http://my.example.com/mydata" elementFormDefault="unqualified" attributeFormDefault="unqualified" version="0.2" xml:lang="en" jaxb:version="2.0"> 

JAXB ràng buộc khối chú thích, chèn ngay sau phần tử gốc trong XSD:

<xs:annotation> 
    <xs:appinfo> 
     <jaxb:globalBindings> 
      <jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" printMethod="javax.xml.bind.DatatypeConverter.printDateTime" /> 
     </jaxb:globalBindings> 
    </xs:appinfo> 
</xs:annotation> 

Kể từ khi xs XML: Trường dateTime cũng lưu trữ múi giờ, có thể tốt hơn nếu tôi làm việc với Lịch thay vì Ngày kể từ khi các đối tượng Lịch có API khá tốt để làm việc với các ngôn ngữ và múi giờ. Trong mọi trường hợp, tôi hạnh phúc hơn nhiều khi đối phó với các đối tượng Lịch thay vì XMLGregorianCalendar. Không cần cho các phương pháp chuyển đổi mà tôi liệt kê ở trên nữa. Tôi đã không nhận được tất cả các cách để java.util.Date, nhưng đủ gần!

+0

Sắp xếp sang một bên, nhưng tại sao bạn phải đối phó với các đối tượng XMLGregorianCalendar ngay từ đầu? Họ rất khó chịu. Nếu chúng đến từ jaxb, bạn có thể sử dụng @XMLTypeAdapter để liên kết trực tiếp với java.util.Date. Tất nhiên nếu bạn đang tự động tạo ra một lược đồ, việc thay đổi các đối tượng có thể gây khó chịu khi bạn tạo lại. – Affe

+0

@Affe Tôi tự động tạo ra một lược đồ để tôi không thể thực hiện bất kỳ thay đổi thủ công nào đối với các lớp JAXB được tạo ra –

+0

Đây có phải là http://stackoverflow.com/questions/835889/java-util-date-to -xmlgregoriancalendar? –

Trả lời

44

Tại sao không sử dụng tệp ràng buộc bên ngoài để yêu cầu XJC tạo các trường java.util.Date thay vì XMLGregorianCalendar?

Xem thêm: - http://weblogs.java.net/blog/kohsuke/archive/2006/03/how_do_i_map_xs.html

+0

Tôi sẽ xem xét điều này. Cảm ơn. –

+0

Không sao cả. JAXB có thể xử lý loại java.util.Date, bạn chỉ cần tạo nó trong mô hình của bạn. Điều này có thể phức tạp. –

+0

Điều đó có hiệu quả với tôi. Xem chỉnh sửa cho câu hỏi của tôi ở trên để biết chi tiết về những gì tôi đã làm. –

5

tôi phải thực hiện một số thay đổi để làm cho nó hoạt động, như một số thứ dường như đã thay đổi trong khi chờ đợi:

  • XJC sẽ phàn nàn rằng bộ chuyển đổi của tôi không mở rộng XmlAdapter
  • một số nhập khẩu kỳ lạ và không cần thiết được rút ra trong (org.w3._2001.XMLSCHEMA)
  • các phương pháp phân tích không phải tĩnh khi mở rộng XmlAdapter, rõ ràng

Dưới đây là một ví dụ làm việc, hy vọng điều này sẽ giúp (Tôi đang sử dụng JodaTime nhưng trong trường hợp này SimpleDate sẽ là đủ):

import java.util.Date; 
import javax.xml.bind.DatatypeConverter; 
import javax.xml.bind.annotation.adapters.XmlAdapter; 
import org.joda.time.DateTime; 

public class DateAdapter extends XmlAdapter<Object, Object> { 
    @Override 
    public Object marshal(Object dt) throws Exception { 
     return new DateTime((Date) dt).toString("YYYY-MM-dd"); 
    } 

    @Override 
     public Object unmarshal(Object s) throws Exception { 
     return DatatypeConverter.parseDate((String) s).getTime(); 
    } 
} 

Trong xSD, tôi đã theo các tài liệu tham khảo tuyệt vời đưa ra ở trên, vì vậy tôi đã bao gồm xml này chú thích:

<xsd:appinfo> 
    <jaxb:schemaBindings> 
     <jaxb:package name="at.mycomp.xml" /> 
    </jaxb:schemaBindings> 
    <jaxb:globalBindings> 
     <jaxb:javaType name="java.util.Date" xmlType="xsd:date" 
       parseMethod="at.mycomp.xml.DateAdapter.unmarshal" 
      printMethod="at.mycomp.xml.DateAdapter.marshal" /> 
    </jaxb:globalBindings> 
</xsd:appinfo> 
+1

Tôi đã trở thành Joda Thời gian fan hâm mộ trong thời gian kể từ khi tôi đặt ra câu hỏi này. Tốt hơn nhiều so với các lớp thời gian và ngày tháng của Java SE. Tuyệt vời để xử lý múi giờ! –

1

Tôi cũng đã có loại đau đầu này. Loại bỏ nó bằng cách đơn giản biểu diễn các trường thời gian như là nguyên thủy trong POJO của tôi. Bây giờ, việc tạo mã máy khách WS của tôi xử lý mọi thứ một cách chính xác và không có nhiều crap XML-to-Java nữa. Và tất nhiên đối phó với millis ở phía Java là đơn giản và không đau. Đá nguyên tắc KISS!

79

Từ XMLGregorianCalendar để java.util.Date bạn chỉ có thể làm:

java.util.Date dt = xmlGregorianCalendarInstance.toGregorianCalendar().getTime(); 
+0

Cảm ơn ... Tôi đã tìm kiếm một cách để chuyển đổi XMLGregorianCalendar thành thời gian tính theo mili giây. – Andez

6

Từ java.util.Date để XMLGregorianCalendar bạn chỉ có thể làm:

import javax.xml.datatype.XMLGregorianCalendar; 
import javax.xml.datatype.DatatypeFactory; 
import java.util.GregorianCalendar; 
...... 
GregorianCalendar gcalendar = new GregorianCalendar(); 
gcalendar.setTime(yourDate); 
XMLGregorianCalendar xmlDate = DatatypeFactory.newInstance().newXMLGregorianCalendar(gcalendar); 

Mã sửa sau khi nhận xét đầu tiên của @ f-puras, bởi nguyên nhân tôi làm sai.

+1

Không hoạt động theo cách bạn đã viết: GregorianCalendar.setTime() sẽ không trả lại bất cứ điều gì. –

0

Tùy chỉnh Lịch và ngày trong khi marshaling

Bước 1: Chuẩn bị jaxb ràng buộc xml cho các thuộc tính tùy chỉnh, Trong trường hợp này tôi chuẩn bị cho ngày và lịch

<jaxb:bindings version="2.1" xmlns:jaxb="http://java.sun.com/xml/ns/jaxb" 
xmlns:xjc="http://java.sun.com/xml/ns/jaxb/xjc" 
xmlns:xs="http://www.w3.org/2001/XMLSchema"> 
<jaxb:globalBindings generateElementProperty="false"> 
<jaxb:serializable uid="1" /> 
<jaxb:javaType name="java.util.Date" xmlType="xs:date" 
    parseMethod="org.apache.cxf.tools.common.DataTypeAdapter.parseDate" 
    printMethod="com.stech.jaxb.util.CalendarTypeConverter.printDate" /> 
<jaxb:javaType name="java.util.Calendar" xmlType="xs:dateTime" 
    parseMethod="javax.xml.bind.DatatypeConverter.parseDateTime" 
    printMethod="com.stech.jaxb.util.CalendarTypeConverter.printCalendar" /> 


Setp 2 : Thêm tệp đính kèm jaxb tùy chỉnh vào Apache hoặc bất kỳ plugin có liên quan nào tại tùy chọn xsd như được đề cập bên dưới

<xsdOption> 
    <xsd>${project.basedir}/src/main/resources/tutorial/xsd/yourxsdfile.xsd</xsd> 
    <packagename>com.tutorial.xml.packagename</packagename> 
    <bindingFile>${project.basedir}/src/main/resources/xsd/jaxbbindings.xml</bindingFile> 
</xsdOption> 

Setp 3: viết mã cho CalendarConverter lớp

package com.stech.jaxb.util; 

import java.text.SimpleDateFormat; 

/** 
* To convert the calendar to JaxB customer format. 
* 
*/ 

public final class CalendarTypeConverter { 

    /** 
    * Calendar to custom format print to XML. 
    * 
    * @param val 
    * @return 
    */ 
    public static String printCalendar(java.util.Calendar val) { 
     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss"); 
     return simpleDateFormat.format(val.getTime()); 
    } 

    /** 
    * Date to custom format print to XML. 
    * 
    * @param val 
    * @return 
    */ 
    public static String printDate(java.util.Date val) { 
     SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); 
     return simpleDateFormat.format(val); 
    } 
} 

Setp 4: Output

<xmlHeader> 
    <creationTime>2014-09-25T07:23:05</creationTime> Calendar class formatted 

    <fileDate>2014-09-25</fileDate> - Date class formatted 
</xmlHeader> 
1

Bạn có thể sử dụng tùy biến này để thay đổi bản đồ mặc định để java. util.Date

<xsd:annotation> 
<xsd:appinfo> 
    <jaxb:globalBindings> 
     <jaxb:javaType name="java.util.Date" xmlType="xsd:dateTime" 
       parseMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.parseDateTime" 
       printMethod="org.apache.cxf.xjc.runtime.DataTypeAdapter.printDateTime"/> 
    </jaxb:globalBindings> 
</xsd:appinfo> 

Các vấn đề liên quan