2011-11-17 4 views
3

私は2つのクラスを持っています。最初にカレンダーフィールドと整数フィールド(tzオフセット)が含まれています。 2番目にはXmlGregorianCalendarフィールドが含まれます。私は、前のクラスと日付を2番目のクラスから比較したい。XMLGregorianCalendarをGregorianCalendarに変換する正しい方法

Calendar cal1 = (Calendar) SerializationUtils.clone(firstClass.getDepartureDatetime()); 
cal1.add(Calendar.MINUTE, -firstClass.getDepartureTzOffset()); 

GregorianCalendar cal2 = secondClass.getDepartureDateTime().toGregorianCalendar(); 
cal2.add(Calendar.MINUTE, -secondClass.getDepartureDateTime().getTimezone()); 

if (LOGGER.isDebugEnabled()) { 
       LOGGER.debug(" - Second [" + DateFormat.getDateTimeInstance().format(cal2.getTime()) + "]"); 
       LOGGER.debug(" - First [" + DateFormat.getDateTimeInstance().format(cal1.getTime()) + "]"); 
} 

私はそのクラスで平等な日付(11月19日午前9時)を設定しました。

システムTZによって、それが(GMT TZで)異なる結果を示す:

Debianのレニー、TZはCETである:

Second [Nov 19, 2011 7:00:00 AM] - wrong! 
First [Nov 19, 2011 8:00:00 AM] -right! 

win7の、TZは、GMT + 3:

Second [Nov 19, 2011 8:30:00 AM] - wrong! 
First [Nov 19, 2011 8:00:00 AM] -right! 

私は間違っていますか?

ありがとうございました。

第一及び第二のクラス

UPDATE:

public class FirstClass implements Serializable { 
    private static final long serialVersionUID = -1150341618306402800L; 

    private Calendar departureDatetime; 

    private Integer departureTzOffset; 

    public Calendar getDepartureDatetime() { 
     return departureDatetime; 
    } 

    public void setDepartureDatetime(Calendar departureDatetime) { 
     this.departureDatetime = departureDatetime; 
    } 

    public Integer getDepartureTzOffset() { 
     return departureTzOffset; 
    } 

    public void setDepartureTzOffset(Integer departureTzOffset) { 
     this.departureTzOffset = departureTzOffset; 
    } 
} 

public class SecondClass implements Serializable 
{ 

    private final static long serialVersionUID = 12345L; 

    protected XMLGregorianCalendar departureDateTime; 

    public XMLGregorianCalendar getDepartureDateTime() { 
     return departureDateTime; 
    } 

    public void setDepartureDateTime(XMLGregorianCalendar value) { 
     this.departureDateTime = value; 
    } 
} 

SerializationUtilsは、Apacheコモンズ・ラングのLIBからorg.apache.commons.lang.SerializationUtilsです。

+0

あなたはそのテストケースを少し簡略化できますか? firstClassとsecondClassとSerializationUtils.cloneを取り出してください – Thilo

+0

@Thiloアップデートを参照してください – ninja

答えて

1

(Calendar)SerializationUtils.clone(firstClass.getDepartureDatetime())を呼び出すと、タイムゾーンに問題が発生しました。タイムゾーンはサーバーTZに設定されていました。

0

最初に質問する必要があります:自分は何をしようとしていますか?

GregorianCalendar gc; 
XMLGregorianCalendar xc; 
gc = xc.toGregorianCalendar(); 
xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc); 

しかし、それはあなたの問題の核心ではないようです。GregorianCalendarのとたXMLGregorianCalendarを変換することは簡単です。タイムゾーンの変換を実行しようとしていますか? IMHO theは、表示時間に変換をシフトすると(実際にはフォーマットの問題であるため)、GregorianCalendarとXMLGregorianCalendarの両方でタイムゾーン情報を持ち、2つのヘルパークラスを取り除くという事実を利用して、 。

TimeZone cet = TimeZone.getTimeZone("CET"); 
TimeZone utc = TimeZone.getTimeZone("UTC"); 
GregorianCalendar gc = new GregorianCalendar(); 
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss Z"); 

@Test 
public void testNow() throws DatatypeConfigurationException { 
    df.setTimeZone(gc.getTimeZone()); 
    log.info(" - Gregorian LOCAL [" + df.format(gc.getTime()) + "]"); 
    df.setTimeZone(cet); 
    log.info(" - Gregorian CET [" + df.format(gc.getTime()) + "]"); 
    df.setTimeZone(utc); 
    String gcs = df.format(gc.getTime()); 
    log.info(" - Gregorian UTC [" + df.format(gc.getTime()) + "]"); 
    XMLGregorianCalendar xc = DatatypeFactory.newInstance().newXMLGregorianCalendar(gc); 
    df.setTimeZone(xc.getTimeZone(0)); 
    log.info(" - XML RAW [" + df.format(xc.toGregorianCalendar().getTime()) + "]"); 
    df.setTimeZone(cet); 
    log.info(" - XML CET [" + df.format(xc.toGregorianCalendar().getTime()) + "]"); 
    df.setTimeZone(utc); 
    String xcs = df.format(xc.toGregorianCalendar().getTime()); 
    log.info(" - XML UTC [" + df.format(xc.toGregorianCalendar().getTime()) + "]"); 
    assertEquals(gcs, xcs); 
} 

おそらく、問題は入力の消毒の問題です。おそらく世界中の空港からの飛行機にdepartureTime変数があり、明示的なタイムゾーン情報を持たないデータソースから取得し、代わりに「空港の現地時間」と仮定します。それはヘルパークラスを説明しますが、その場合は、入力が発生した場合にその入力を消毒する必要があります。 「空港の現地時間」を決定することは時々難しいことがあります(夏時間から翌年に標準に切り替えるか、DSTを完全に廃止することを選択する可能性があります。たとえば、空港では米国のタイムゾーンを切り替えることさえできます)。東部から中央部への郡の移動は、あなたが思うより頻繁に起こります)。この問題を解決するには、コンピュータのロケールデータベースを使用して、独自のタイムゾーン演算を実行しないでください。

関連する問題