UTC
始終使用UTC進行數據交換和這種讀數記錄。始終,始終使用UTC。將UTC視爲一個真實時間和其他時區與UTC的偏差。
順便說一句,Daylight Saving Time (DST)是不是唯一的問題是擔心區劃日期時間值。其他異常發生在各個時區,導致wall-clock time向前或向後移動。解決方案很簡單:避免使用所有時區 - 使用UTC。
Instant
的Instant
類捕獲UTC時間線與納秒的分辨率上一會兒。這應該是你去上課的日期時間工作。
Instant instant = Instant.now();
字符串
用於記錄,生成標準ISO 8601格式的字符串。堅持採用經過驗證的ISO 8601格式,而不是發明自己的產品。
包括Instant
的java.time類在解析/生成字符串時默認使用ISO 8601格式。所以不需要指定格式化模式。
String output = instant.toString();
2016-11-02T21:10:05.321Z
Instant instant = Instant.parse("2016-11-02T21:10:05.321Z");
而且始終在您的日期世紀20
。忽略只會爲錯誤解釋中的錯誤創造很多機會。存儲和內存真的很便宜,我們可以負擔兩個額外的數字。
時區指針
始終包括時區或偏移從-UTC指標與序列化日期時間值。
在上面看到的Instant::toString
結果中,Z
代表Zulu
,表示UTC。
解析字符串
下面是代碼來解析您的日期時間字符串。我們首先解析爲LocalDateTime
,沒有任何時區或偏移量,因爲您的輸入缺少任何時區或偏移量的指示符。然後我們分配一個時區來獲得ZonedDateTime
,以瞭解它如何處理DST切換的時刻。
我認爲問題所在時區使用凌晨2點的DST回退割接。作爲這樣的例子,我使用America/Montreal
。
List<String> inputs = new ArrayList<>(2);
inputs.add("141102 0115"); // 1 AM
inputs.add("141102 0215"); // 2 AM
for(String input : inputs) {
DateTimeFormatter f = DateTimeFormatter.ofPattern("uuMMdd HHmm");
LocalDateTime ldt = LocalDateTime.parse(input , f);
// At 2 AM in this zone, the clock falls back one hour for DST cutover. The 1 AM hour repeats.
ZoneId z = ZoneId.of("America/Montreal");
ZonedDateTime zdt = ldt.atZone(z);
System.out.println("input: " + input);
System.out.println("ldt: " + ldt);
System.out.println("zdt: " + zdt);
System.out.println("instant: " + zdt.toInstant());
System.out.println("");
}
輸入:141102 0115
LDT:2014-11-02T01:15
ZDT:2014-11-02T01:15-04:00 [美國/蒙特利爾]
瞬間:2014-11-02T05:15:00Z
......還有......
輸入:141102 0215
LDT:2014-11-02T02:15
ZDT:2014-11-02T02:15-05:00 [美國/蒙特利爾]
瞬間: 2014-11-02T07:15:00Z
您可以see this code live in IdeOne.com。請注意UTC值的兩小時差異(Z
)。
我們看到的行爲被記錄在案。
在大多數情況下,本地日期時間只有一個有效偏移量。在時鐘重新設置的情況下,有兩個有效的偏移量。此方法使用通常對應於「夏季」的較早的偏移量。
上午1點15分含糊不清,可能是第一或第二次出現java。時間與第一次一樣。
你可以玩猜謎遊戲來嘗試調整這些糟糕設計的字符串。如果您確定在每個時鐘小時內至少有一個樣本,則可以跟蹤以前的樣本並查看正在處理的樣本是否比以前的時鐘早。如果是這樣,你可以認爲這是一個DST後退切換,並添加一小時plusHours(1)
。
if(processingZdt.toLocalDateTime().isBefore(previousZdt.toLocalDateTime()) {
processingZdt.plusHours(1) ; // A hack; I am *not* recommending this.
…
但是,這是一個解決方案的冒險攻擊。我不確定這項工作,因爲我沒有想到它通過。如果絕望,也許你可以讓它工作。
明智的做法是預防:使用UTC。
所以你真正想要做的是將日期轉換爲一個文件名,使用的時區在夏天不會改變它的偏移量,對吧? –
它不是文件名,而是文件中有'timestamp'的一行。我想在dst的一個小時內轉換該時間戳,以便我沒有缺口或重複的條目。 – DHines
好的,但不會只使用日期格式沒有夏時制的時區達到那個目的?或者我錯過了什麼?標準做法是在日誌文件中使用UTC作爲時間戳,但大概您更希望在冬天您的時區與您的時區保持一致。 –