簡體   English   中英

使用SimpleDateFormat解析日期不正確

[英]Incorrect date parsing with SimpleDateFormat

我有一個帶有date()和time()列的MySQL表,例如

CREATE TABLE `vol` (
  `ID` bigint(20) unsigned NOT NULL,
  `DEPART_DATE_VOL` date NOT NULL,
  `DEPART_HEURE_VOL` time NOT NULL,
  `ARRIVEE_DATE_VOL` date NOT NULL,
  `ARRIVEE_HEURE_VOL` time NOT NULL,
  PRIMARY KEY (`ID`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

我需要在WHERE子句中使用date()查詢行,所以我沒有datetime()或時間戳(此外,我無法修改數據庫)

當在我的DAO中獲取信息時,我會合並日期和時間列以解析Java日期,例如:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
addon.setDateDepart(sdf.parse(rs.getString(DEPART_DATE_VOL) + " " + rs.getString(DEPART_HEURE_VOL)));
addon.setDateArrivee(sdf.parse(rs.getString(ARRIVEE_DATE_VOL) + " " + rs.getString(ARRIVEE_HEURE_VOL)));

對於有出發日期的行:

  • 2018-02-26 10:50:00生成的Java日期正確

但對於到達日期:

  • 2018-02-26 12:20:00結果Java日期設置為2018-02-26T00:20:00

TMP解決方案

現在,我會堅持

addon.setDateDepart(new LocalDateTime(rs.getString(DEPART_DATE_VOL) + "T" + rs.getString(DEPART_HEURE_VOL)).toDate());

addon.setDateArrivee(new LocalDateTime(rs.getString(ARRIVEE_DATE_VOL) + "T" + rs.getString(ARRIVEE_HEURE_VOL)).toDate());

這似乎可行,但我不確定我是否會遇到時區問題...

在時間部分嘗試使用HH:mm:ss hh用於“上午/下午(1-12)的小時數”,請參閱javadoc

  1. 在數據庫中使用timestamp數據類型,而不要使用單獨的列作為日期和時間。 MySQL timestamp采用UTC格式,因此應避免在數據庫端出現任何時區問題。
  2. 使用java.time (現代的Java日期和時間API)。 諸如Date類的舊日期和時間類設計欠佳,尤其是SimpleDateFormat尤其麻煩,因此請避免使用它。
  3. 在Java程序和數據庫之間傳輸日期時間對象,而不是字符串。

閱讀更多有關此問題的信息:針對地理位置不同的用戶的日期操縱/存儲的Java最佳實踐 如果您不能做到所有這些,請盡力而為。

細節

如果可以在數據庫中存儲時間戳,則可以將其作為java.time.Instant檢索:

Instant departVol = rs.getObject(DEPART_INSTANT_VOL, Instant.class);

如果您無法更改addon.setDateDepart()接受的類型,請轉換為以下Date

addon.setDateDepart(Date.from(departVol));

或在使用ThreeTen Backport的版本中,即java.time向Java 6和7的java.time移植:

addon.setDateDepart(DateTimeUtils.toDate(departVol));

如果無法更改數據庫設計,仍然可以從中檢索java.time對象:

LocalDate departDateVol = rs.getObject(DEPART_DATE_VOL, LocalDate.class);
LocalTime departHeureVol = rs.getObject(DEPART_HEURE_VOL, LocalTime.class);
LocalDateTime departDateHeureVol = LocalDateTime.of(departDateVol, departHeureVol);

轉換為老式Date很不穩定,因為正如您所說,可能存在時區問題。 嘗試:

addon.setDateDepart(
        Date.from(departDateHeureVol.atZone(ZoneId.systemDefault()).toInstant()));

如果此處似乎存在時區問題,則需要指定正確的時區而不是ZoneId.systemDefault()

如果您的Java版本或JDBC驅動程序不支持從結果集中獲取正確的日期時間對象,則使用現代類可以很容易地解析字符串:

LocalDate departDateVol = LocalDate.parse(rs.getString(DEPART_DATE_VOL);
LocalTime departHeureVol = LocalTime.parse(rs.getString(DEPART_HEURE_VOL);

與這些對象一樣,繼續進行。

PS我還沒有測試我的代碼段。 如果有錯別字,而您卻不能自己解決,請還原。

您的代碼出了什么問題?

kevmo314是正確的是小寫字母hh在格式模式字符串是與AM或PM小時,從1到12,那么12:20:00 確實意味着00:20:00 要在24小時制上解釋12在一天中的0到23之間使用大寫HH

鏈接: ThreeTen backport主頁

暫無
暫無

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

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