日期處理-最佳實踐
阿新 • • 發佈:2021-01-31
文章目錄
一、舊API轉新API
如果要把舊式的Date或Calendar轉換為新API物件,可以通過toInstant()方法轉換為Instant物件,再繼續轉換為ZonedDateTime
public static void old2New() {
// Date -> Instant:
Instant ins1 = new Date().toInstant();
// Calendar -> Instant -> ZonedDateTime:
Calendar calendar = Calendar.getInstance();
Instant ins2 = calendar.toInstant();
// 舊的TimeZone提供了一個toZoneId(),可以把自己變成新的ZoneId。
ZonedDateTime zdt = ins2.atZone(calendar.getTimeZone().toZoneId());
}
二、新API轉舊API
如果要把新的ZonedDateTime轉換為舊的API物件,只能藉助long型時間戳做一個“中轉”:
public static void new2Old() {
// ZonedDateTime -> long:
ZonedDateTime zdt = ZonedDateTime.now();
long ts = zdt.toEpochSecond() * 1000;
// long -> Date
Date date = new Date(ts);
// long -> Calendar
Calendar calendar = Calendar.getInstance();
calendar. clear();
// 新的ZoneId轉換為舊的TimeZone,需要藉助ZoneId.getId()返回的String完成。
calendar.setTimeZone(TimeZone.getTimeZone(zdt.getZone().getId()));
calendar.setTimeInMillis(ts);
}
三、與資料庫對映
資料庫 | 對應Java類(舊) | 對應Java類(新) |
---|---|---|
DATETIME | java.util.Date | LocalDateTime |
DATE | java.sql.Date | LocalDate |
TIME | java.sql.Time | LocalTime |
TIMESTAMP | java.sql.Timestamp | LocalDateTime |
實際上
實際上,在資料庫中,我們需要儲存的最常用的是時刻(Instant),因為有了時刻資訊,就可以根據使用者自己選擇的時區,顯示出正確的本地時間。所以,最好的方法是直接用長整數long表示,在資料庫中儲存為BIGINT型別。
通過儲存一個long型時間戳,我們可以編寫一個timestampToString()的方法,非常簡單地為不同使用者以不同的偏好來顯示不同的本地時間:
public static String timestampToString(long epochMilli, Locale lo, String zoneId) {
Instant ins = Instant.ofEpochMilli(epochMilli);
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM, FormatStyle.SHORT);
return f.withLocale(lo).format(ZonedDateTime.ofInstant(ins, ZoneId.of(zoneId)));
}
public static void main(String[] args) {
long ts = 1574208900000L;
System.out.println(timestampToString(ts, Locale.CHINA, "Asia/Shanghai"));
// 2019年11月20日 上午8:15
System.out.println(timestampToString(ts, Locale.US, "America/New_York"));
// Nov 19, 2019, 7:15 PM
}