簡體   English   中英

如何使用ObjectOutputStream和ObjectInputStream在Java中處理夏時制?

[英]How to handle daylight saving time in Java using ObjectOutputStream and ObjectInputStream?

我正在傳遞一個哈希圖,其中包含日期為

2019-03-08 00:00:00.0

到servlet並在servlet端讀取hashmap時,我正在獲取日期

2019-03-07 23:00:00.0

它只能在夏令時轉換一小時。如何在Java中處理呢?

java.util.Date d = new java.util.Date();
d.setDate(06);
d.setMonth(02);
d.setYear(2018);
d.setHours(23);
d.setMinutes(59);
d.setSeconds(00);

ObjectInputStream is = new ObjectInputStream(request.getInputStream());
java.util.Date obj=(java.util.Date)is.readObject();
ObjectOutputStream objectOutputStream = new ObjectOutputStream(response.getOutputStream());
Vector vector = new Vector();
vector.add(d);
objectOutputStream.writeObject(vector);
objectOutputStream.flush();
objectOutputStream.close();

從Java類中讀取時,Iam減少了一個小時。

如果服務器時區設置未考慮夏令時(DST),可能會發生這種情況。 例如,我以美國/亞松森時區為例。 亞松森是巴拉圭最大的城市和首都。 巴拉圭在標准時間的偏移量為-04:00,但在夏季的偏移量為-03:00。 夏季時間仍在3月8日生效,直到3月24日。

首先說明出了什么問題:

    System.setProperty("user.timezone", ZoneId.ofOffset("GMT", ZoneOffset.ofHours(-4)).getId());

    // Send a timestamp from America/Asuncion time zone
    ZoneId zone = ZoneId.of("America/Asuncion");
    // Create the timestamp as March 8 at 00:00:00
    Instant testTime
            = ZonedDateTime.of(2019, 3, 8, 0, 0, 0, 0, zone).toInstant();
    Timestamp ts = Timestamp.from(testTime);

    try (ByteArrayOutputStream baos = new ByteArrayOutputStream()) {
        try (ObjectOutputStream objectOutputStream = new ObjectOutputStream(baos)) {
            objectOutputStream.writeObject(ts);
        }
        byte[] ba = baos.toByteArray();
        try (ObjectInputStream is = new ObjectInputStream(new ByteArrayInputStream(ba))) {
            java.util.Date obj = (java.util.Date) is.readObject();
            System.out.println(obj);
        }
    }

對於這個簡單的演示,我們不需要單獨的客戶端和服務器代碼。 我創建一個在相關時區中具有已知日期和時間的Timestamp對象,將其寫入ObjectOutputStream並使用相同的基礎字節從ObjectInputStream讀取回。 我得到的是代表同一時間點Timestamp 為了演示接收器打印時會發生什么,我將默認時區設置在頂部。 我正在使用-04:00的恆定偏移量來演示服務器時區未考慮夏令時時會發生什么。 它打印:

2019-03-07 23:00:00.0

因此,您得到的結果相同。 這是因為-令人困惑Timestamp.toString使用JVM的時區設置來生成字符串。

怎么修?

當我們知道Timestamp是從America / Asuncion時區發送的時,我們可以在服務器上顯式使用該時區:

            java.util.Date obj = (java.util.Date) is.readObject();

            ZonedDateTime timeAsSent = obj.toInstant().atZone(zone);
            System.out.println(timeAsSent);

2019-03-08T00:00-03:00 [美國/亞松森]

現在時間與最初寫入對象輸出流的時間一致。

更好的修復

如果可以的話,請完全避免使用舊的類DateTimestamp 這些課程的設計不佳,會在您身上耍花樣。 他們也早已過時。 而是將ZonedDateTimeInstant寫入客戶端的對象流中,當然還要在服務器端讀取相同的類型。 這樣就不會有驚喜的余地。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM