LocalDateTime
-
-
- 1. 環境
- 2. 代碼
-
- 2.1 LocalDate: 擷取年月日
- 2.2 LocalTime: 擷取時分秒
- 2.3 LocalDateTime: 擷取年月日時分秒
- 2.4 LocalDateTime 年月日時分秒的 操作.
- 2.5 時間計算
- 2.6 格式化時間
- 2.7 解析時間:
- 2.8 看得懂的時間輸出
- 2.9 日期加減日期
- 2.91 LocalDateTime.util()
- 2.92 Duration.between()
- 7.0 相關工具類
-
1. 環境
Since JDK8
LocalDateTime 的好處- 每一個時間對象,都是線程安全的
- 每一個對象都沒有公開的構造器,如果需要一個對象你首先想的不是 new,而是靜态工廠方法: now、of、from
- 如果你喜歡敲全類名,請在使用時間api時忘記java.util和java.text,記住java.time
2. 代碼
為什麼建議使用你 LocalDateTime ,而不是 Date?
根據這篇部落格學習,下面練習的代碼, 并附上了輸出結果.
JDK8新增的 java.time
JDK8 新增的 java.time 這篇講得好
JDK8 的新特性 這個不錯
2.1 LocalDate: 擷取年月日
/** LocalDate: 擷取年月日 */
@Test
public void m1() {
//擷取目前年月日
LocalDate localDate = LocalDate.now();
//構造指定的年月日
LocalDate localDate1 = LocalDate.of(2019, 9, 10);
System.out.println("localDate = " + localDate); // localDate = 2020-07-04
System.out.println("localDate1 = " + localDate1); // localDate1 = 2019-09-10
int year = localDate.getYear();
System.out.println("year = " + year); // year = 2020
int year1 = localDate.get(ChronoField.YEAR);
System.out.println("year1= " + year1); // year1= 2020
Month month = localDate.getMonth();
System.out.println("month= " + month); // month= JULY
int month1 = localDate.get(ChronoField.MONTH_OF_YEAR);
System.out.println("month1= " + month1); // month1= 7
int day = localDate.getDayOfMonth();
System.out.println("day= " + day); // day= 6
int day1 = localDate.get(ChronoField.DAY_OF_MONTH);
System.out.println("day1= " + day1); // day1= 6
DayOfWeek dayOfWeek = localDate.getDayOfWeek();
System.out.println("dayOfWeek= " + dayOfWeek); // dayOfWeek= MONDAY
int dayOfWeek1 = localDate.get(ChronoField.DAY_OF_WEEK);
System.out.println("dayOfWeek1= " + dayOfWeek1); // dayOfWeek1= 1
}
2.2 LocalTime: 擷取時分秒
/** LocalTime: 擷取時分秒 */
@Test
public void m2() {
// 擷取目前時分秒
LocalTime localTime = LocalTime.now();
// 構造指定的時分秒
LocalTime localTime1 = LocalTime.of(10, 30, 55);
System.out.println("localTime= " + localTime); // localTime= 10:34:27.591553
System.out.println("localTime1= " + localTime1); // localTime1= 10:30:55
//擷取小時
int hour = localTime.getHour();
int hour1 = localTime.get(ChronoField.HOUR_OF_DAY);
System.out.println("hour= " + hour); // hour= 10
System.out.println("hour1= " + hour1); // hour1= 10
//擷取分
int minute = localTime.getMinute();
int minute1 = localTime.get(ChronoField.MINUTE_OF_HOUR);
System.out.println("minute = " + minute); // minute = 34
System.out.println("minute1 = " + minute1); // minute1 = 34
//擷取秒
int second = localTime.getSecond();
int second1 = localTime.get(ChronoField.SECOND_OF_MINUTE);
System.out.println("second = " + second); // second = 27
System.out.println("second1 = " + second1); // second1 = 27
}
2.3 LocalDateTime: 擷取年月日時分秒
/** LocalDateTime: 擷取年月日時分秒 */
@Test
public void m3() {
//擷取目前年月日
LocalDate localDate = LocalDate.now();
// 擷取目前時分秒
LocalTime localTime = LocalTime.now();
LocalDateTime localDateTime = LocalDateTime.now();
LocalDateTime localDateTime1 = LocalDateTime.of(LocalDate.of(2020, 7, 3), LocalTime.of(10, 38, 55));
LocalDateTime localDateTime2 = LocalDateTime.of(2019, Month.SEPTEMBER, 10, 14, 46, 56);
LocalDateTime localDateTime3 = localDate.atTime(localTime); // 相當于 localDate + localTime = LocalDateTime
LocalDateTime localDateTime4 = localTime.atDate(localDate); // 相當于 localDate + localTime = LocalDateTime
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-07-06T10:40:10.128524
System.out.println("localDateTime1 = " + localDateTime1); // localDateTime1 = 2020-07-03T10:38:55
System.out.println("localDateTime2 = " + localDateTime2); // localDateTime2 = 2019-09-10T14:46:56
System.out.println("localDateTime3 = " + localDateTime3); // localDateTime3 = 2020-07-08T14:58:20.685306
System.out.println("localDateTime4 = " + localDateTime4); // localDateTime4 = 2020-07-08T14:58:20.685306
// 擷取LocalDate
LocalDate localDate2 = localDateTime.toLocalDate();
// 擷取LocalTime
LocalTime localTime2 = localDateTime.toLocalTime();
System.out.println("localDate2 = " + localDate2); // localDate2 = 2020-07-08; localDateTime = 2020-07-08T15:05:34.630987
System.out.println("localTime2 = " + localTime2); // localTime2 = 15:05:34.630987; localDateTime = 2020-07-08T15:05:34.630987
// 擷取秒數. ( 用 System.currentTimeMills()更友善 )
Instant instant = Instant.now();
long currentSecond = instant.getEpochSecond();
long timeStamp1 = instant.toEpochMilli();
long timeStamp2 = System.currentTimeMillis();
System.out.println("currentSecond = " + currentSecond); // currentSecond = 1594192226
System.out.println("timeStamp1 = " + timeStamp1); // timeStamp1 = 1594192226826
System.out.println("timeStamp2 = " + timeStamp2); // timeStamp2 = 1594192226826
}
2.4 LocalDateTime 年月日時分秒的 操作.
/**
* LocalDateTime 年月日時分秒的 操作.
*
* LocalDate、LocalTime、LocalDateTime、Instant為不可變對象,修改這些對象對象會傳回一個副本
*
* plusXX(): 在原來的基礎上加
* withXX(): 直接設定值
*/
@Test
public void m4() {
LocalDateTime localDateTime = LocalDateTime.of(1997, Month.FEBRUARY, 2, 9, 13, 14);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-02-02T09:13:14
//增加一年 plusYears()
localDateTime = localDateTime.plusYears(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-02-02T09:13:14
localDateTime = localDateTime.plus(1, ChronoUnit.YEARS);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1999-02-02T09:13:14
// 減少一年 minusYears()
localDateTime = localDateTime.minusYears(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-02-02T09:13:14
//減少一個月 minusMonths(); 同理增加一月 就是 plusMonths(); 還可以修改 日、時分秒、周等等.
localDateTime = localDateTime.minusMonths(1);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1998-01-02T09:13:14
localDateTime = localDateTime.minus(1, ChronoUnit.MONTHS);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-12-02T09:13:14
/* with: 設定值 */
//修改年為2020
localDateTime = localDateTime.withYear(2020);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2020-12-02T09:13:14
//修改為2022
localDateTime = localDateTime.with(ChronoField.YEAR, 2022);
System.out.println("localDateTime = " + localDateTime); // localDateTime = 2022-12-02T09:13:14
}
2.5 時間計算
/**
* 時間計算
*
* 比如有些時候想知道這個月的最後一天是幾号、下個周末是幾号,通過提供的時間和日期API可以很快得到答案
*/
@Test
public void m5() {
LocalDate localDate = LocalDate.now();
System.out.println("localDate = " + localDate); // localDate = 2020-07-08
// 年的第一天
LocalDate localDate1 = localDate.with(TemporalAdjusters.firstDayOfYear());
System.out.println("localDate1 = " + localDate1); // localDate1 = 2020-01-01
// 月的第一天; 還有很多其他的, 點進去看吧.
localDate = localDate.with(TemporalAdjusters.firstDayOfMonth());
System.out.println("localDate = " + localDate); // localDate = 2020-07-01
}
2.6 格式化時間
LocalDateTime -> String
/**
* 格式化時間
*
* DateTimeFormatter預設提供了多種格式化方式,如果預設提供的不能滿足要求,可以通過DateTimeFormatter的ofPattern方法建立自定義格式化方式
*/
@Test
public void m6() {
LocalDate localDate = LocalDate.of(2019, 9, 10);
String s1 = localDate.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = localDate.format(DateTimeFormatter.ISO_LOCAL_DATE);
//自定義格式化
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String s3 = localDate.format(dateTimeFormatter);
System.out.println("localDate = " + localDate); // localDate = 2019-09-10
System.out.println("s1 = " + s1); // s1 = 20190910
System.out.println("s2 = " + s2); // s2 = 2019-09-10
System.out.println("s3 = " + s3); // s3 = 10/09/2019
// LocalDateTime 轉換成 特定格式的 字元串
LocalDateTime now = LocalDateTime.now();
String nowStr1 = now.format(DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss"));
String nowStr2 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"));
System.out.println("now = " + now); // now = 2020-07-08T16:41:12.647672
System.out.println("nowStr1 = " + nowStr1); // nowStr1 = 2020/07/08 16:41:12
System.out.println("nowStr2 = " + nowStr2); // nowStr2 = 2020-07-08 16:42
// format 是線程不安全的. 用 parse() 方法時候 需要特定格式的, 并且還要 try-catch
String dateStr = "";
Date date = new Date();
if (date != null) {
dateStr = new SimpleDateFormat("yyyy MM dd HH:mm").format(date);
}
System.out.println("dateStr = " + dateStr); // dateStr = 2020 07 08 16:43
}
2.7 解析時間:
String -> LocalDateTime
/**
* 解析時間: 感覺還是 SimpleDateTime好用, 即使它線程不安全, 但是在開辟一個線程處理 好了.
*
* 注意:
* 1. 要解析的字元串, 格式必須要和 設定的pattern是一緻的, 不然就報錯。
* 2. 使用 解析必須要 try-catch, SimpleDateFormate的parse還會提示要處理異常, LocalDateTime居然不提示...
*/
@Test
public void m7() {
String dateStr = "1997-02-02 17:13:14";
LocalDateTime localDateTime = null;
try {
localDateTime = LocalDateTime.parse(dateStr, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("localDateTime = " + localDateTime); // localDateTime = 1997-02-02T17:13:14
/*
* 自我感覺 沒 SimpleDateTime好用啊... 雖然 SimpleDateTime是線程不安全的
*
* 1. LocatDateTime的parse() 使用 LocalDateTime 那字元串必須要 年月日 時分秒, 如果隻寫年月日, 就算 ofPattern("yyyy-MM-dd") 也不行. 需要用 LocalDate.parse()
* 2. 而SimpleDateFormat.parse() 就算隻寫了 "yyyy-MM-dd" 隻需要保證 年月日是此格式即可, 後面的時分秒無所謂.
*/
Date date = null;
try {
date = new SimpleDateFormat("yyyy-MM-dd").parse(dateStr);
} catch (ParseException e) {
e.printStackTrace();
}
System.out.println("date = " + date); // date = Sun Feb 02 00:00:00 CST 1997
// LocalDate, 這樣是不會報錯的, 字元串隻寫了年月日 就必須用 LocalDate來解析.
String dateStr2 = "1997-02-02";
LocalDate localDate = null;
try {
localDate = LocalDate.parse(dateStr2, DateTimeFormatter.ofPattern("yyyy-MM-dd"));
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("localDate = " + localDate); // localDate = 1997-02-02
}
2.8 看得懂的時間輸出
挺好用的東西… JDK 14 會報錯, JDK8沒問題
/** 挺好用的東西.. JDK 14 會報錯, JDK8沒問題 */
@Test
public void m8() {
LocalDateTime d1=LocalDateTime.now();
FormatStyle dateTimeStyle=FormatStyle.LONG;
Locale.setDefault(Locale.CHINA);
DateTimeFormatter formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
String format = d1.format(formater);
System.out.println(format);//2017年11月30日 下午04時10分32秒
dateTimeStyle=FormatStyle.MEDIUM;
Locale.setDefault(Locale.CHINA);
formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
format = d1.format(formater);
System.out.println(format);//2017-11-30 16:10:32
Locale.setDefault(Locale.UK);
format = d1.format(formater);
System.out.println(formater);//2017-11-30 16:10:32
// Locale.setDefault 和 DateTimeFormatter.ofLocalizedDateTime 必須重新設定一次, 否則像上面這樣的輸出結果和 第2個一樣
Locale.setDefault(Locale.UK);
formater=DateTimeFormatter.ofLocalizedDateTime(dateTimeStyle);
format = d1.format(formater);
System.out.println(format);//30-Nov-2017 16:10:32
}
2.9 日期加減日期
2.91 LocalDateTime.util()
2.92 Duration.between()
public class Test02_LocalDateTime {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.systemDefault();
System.out.println("zoneId = " + zoneId); // zoneId = Asia/Shanghai
LocalDateTime now = LocalDateTime.now();
String dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1);
LocalDateTime loc = LocalDateTime.of(1997, 07, 13, 14, 55, 59);
String dateStr2 = loc.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("locStr = " + dateStr2); // dateStr2 = 1997-07-13 14:55:00
/// JDK14 報錯, JDK8 可以.
// FormatStyle formatStyle = FormatStyle.LONG;
// Locale.setDefault(Locale.CHINA);
// DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofLocalizedDateTime(formatStyle);
// String f1 = now.format(dateTimeFormatter);
// System.out.println("f1 = " + f1);
/*
* 日期加減日期
*
* 1. minusXX/plusXX: 隻能單獨加減年月日 or 時分秒的.
* TemporalAmount 實作類之一是: Duration
* 3. LocalDateTime.until(): 第二個參數 - 第一個參數 的出來的正負天數.
* 4. Duration.between(): 第二個參數 - 第一個參數 的出來的正負天數.
*/
Duration duration = Duration.between(now, loc);
System.out.println("duration = " + duration); // duration = PT-201690H-36M-19.603835S .
now = LocalDateTime.of(2020, 7, 16, 10, 13, 14);
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 2020-07-16 10:13:14
// locStr = 1997-07-13 14:55:59
now = now.minusYears(loc.getYear()); // 1997
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-16 10:13:14
now = now.minusDays(loc.getDayOfMonth()); // 13
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-03 10:13:14
now = now.plusDays(13);
TemporalAmount amountToSubtract = Duration.ofDays(13);
now = now.minus(amountToSubtract);
dateStr1 = now.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("dateStr1 = " + dateStr1); // dateStr1 = 0023-07-03 10:13:14
/*
* 時間與時間的計算
*
* 兩個時間之間的計算,結果為一個量。如,計算兩個時間相隔多少天。
* 舉例,計算2016年元旦到五一勞動節相隔多少天?
*/
LocalDateTime d1=LocalDateTime.of(2020, 07, 16, 11, 04);
LocalDateTime d2=LocalDateTime.of(1997, 01, 03, 13, 14);
System.err.println("d1 = " + d1.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // d1 = 2020-07-16 11:04:00
System.err.println("d2 = " + d2.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"))); // d2 = 1997-01-03 13:14:00
long interval = d2.until(d1, ChronoUnit.DAYS);
System.out.println(interval); // 8594
// 也可以使用時間量的計算:
Duration d = Duration.between(d1, d2);
System.out.println(d.toDays()); // -8594
System.out.println(d.toHours()); // -206277
long age = d2.until(d1, ChronoUnit.YEARS);
System.out.println("age = " + age); // age = 23, 這個算年齡... 但是不算天數, 自己寫的 age計算的工具類 會把天算上.
}
}
7.0 相關工具類
/** 聽說是 解決 SImpleDateFormat線程不安全問題 */
private static final ThreadLocal<SimpleDateFormat> local = new ThreadLocal<SimpleDateFormat>();
private static SimpleDateFormat getTime() {
SimpleDateFormat sdf = local.get();
if (sdf == null) {
sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
local.set(sdf);
}
return sdf;
}
/** LocalDate轉Date */
public static Date localDateToDate(LocalDate localDate) {
if (null == localDate) {
return null;
}
ZonedDateTime zonedDateTime = localDate.atStartOfDay(ZoneId.systemDefault());
return Date.from(zonedDateTime.toInstant());
}
/** Date轉LocalDate */
public static LocalDate dateToLocalDate(java.util.Date date) {
if (null == date) {
return null;
}
return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
}
/** Date轉換為LocalDateTime */
public static LocalDateTime dateToLocalDateTime(Date date){
if (null == date) {
return null;
}
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
return localDateTime;
}
/** LocalDateTime轉換為Date */
public static Date localDateTimeToDate( LocalDateTime localDateTime){
if (localDateTime == null) {
return null;
}
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
return Date.from(zdt.toInstant());
}