Java 8 在java.time包下推出了一組全新的時間日期API,涵蓋了日期、時間、日期時間、時區、時刻、間隔、時鐘等
新的java.time包下的所有類都是不可變類型而且線程安全的,解決了在此之前日期時間中存在的線程安全、橫跨多包、使用複雜等諸多問題
1、時間和日期
// 本地時間
LocalTime lt = LocalTime.now();
// 本地日期
LocalDate ld = LocalDate.now();
// 本地日期時間
LocalDateTime ldt = LocalDateTime.now();
// 創建一個指定的時間
LocalDateTime ldt = LocalDateTime.of(2012, 2, 12, 12, 12, 12);
// 日期時間轉日期或時間
LocalDate ld = ldt.toLocalDate();
LocalTime lt = ldt.toLocalTime();
2、字符串互轉
// 格式化模版
DateTimeFormatter DATETIME19 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
// 時間轉字符串
String dtStr = DATETIME19.format(LocalDateTime.now());
// 字符串轉時間
LocalDateTime ldt = LocalDateTime.parse(dtStr, DATETIME19);
3、時間運算
//獲取指定單位的值
int year = ldt.getYear();
int day = ldt.getDayOfMonth();
int week = ldt.getDayOfWeek().getValue();
int hour = ldt.getHour();
// 指定時間單位的值
LocalDateTime ldt2 = ldt1.withDayOfMonth(10).withYear(2020); // 返回的是一個新的對象,需要接收
// 在現有時間上做加法
LocalDateTime ldt2 = ldt1.plusYears(2).plusMonths(-2);
// 在現有時間上做減法
LocalDateTime ldt2 = LocalDateTime.now().minus(-2, ChronoUnit.MONTHS).minusDays(3)
// 獲取一天的開始或結束
LocalDateTime ldtStart = LocalDateTime.of(LocalDate.now(), LocalTime.MIN);
LocalDateTime ldtEnd = LocalDateTime.of(LocalDate.now(), LocalTime.MAX);
// 時間是否在指定時間之前
boolean isBefore = ldt1.isBefore(ldt2);
// 時間是否在指定時間之後
boolean isAfter = ldt1.isAfter(ldt2);
// 比較兩個日期是否相等 重寫的equals可以直接比較
boolean equality = ld1.equals(ld2);
// 比較是否是週期性日期,比如 生日 節假日 賬單日 等
MonthDay holiday = MonthDay.of(5, 1); // 五一
boolean equality = holiday.equals(MonthDay.from(LocalDateTime.now())); // 今天是否是五一
4、間隔計算
LocalDateTime ldt1 = LocalDateTime.of(2012, 2, 12, 12, 12, 12);
LocalDateTime ldt2 = LocalDateTime.of(2015, 5, 15, 15, 15, 15);
// 時間的間隔 Duration 表示時分秒的時間量(累計向上單位的差,即計算實際的總共的差)
Duration duration = Duration.between(ldt1, ldt2);
long durnMill = duration.toMillis(); // 計算毫秒差
long durnMin = duration.toMinutes(); // 計算分鐘差
long durnHour = duration.toHours(); // 計算小時差
long durnDay = duration.toDays(); // 計算天數差
// 日期的間隔 Period 表示年月日的時間量(只計算當前單位的差,不累計向上單位的差距)
Period period = Period.between(ldt1.toLocalDate(), ldt2.toLocalDate());
long perdDay = period.getDays(); // 只計算當前差,不累計年月差帶來的天數差
long perdMonth = period.getMonths(); // 只計算當前差,不累計年數差帶來的月數差
long perdYear = period.getYears();
// 計算實際總間隔天數的第二種方法
long diffEehDay =ldt1.toLocalDate().toEpochDay() - ldt2.toLocalDate().toEpochDay();
// 計算指定時間單位之差
long diffChrDay =ChronoUnit.DAYS.between(ldt1, ldt2); // 日期單位之差
long diffChrMin =ChronoUnit.MINUTES.between(ldt1, ldt2); // 分鐘單位之差
5、時間戳、瞬時點、Date、本地時間、轉換
// 時間戳
long timestamp = System.currentTimeMillis();
// 瞬時點
Instant instant = Instant.now();
// Date
Date date = new Date();
// 時間戳 轉 瞬時點
Instant instant = Instant.ofEpochMilli(timestamp);
// 瞬時點 轉 時間戳
long timestamp = instant.toEpochMilli();
// Date 轉 瞬時點
Instant instant = date.toInstant();
// 瞬時點 轉 Date
Date date = Date.from(instant);
// 瞬時點 轉 本地時間
LocalDateTime ldt = LocalDateTime.ofInstant(instant, ZoneId.systemDefault());
// 本地時間 轉 時間戳
long timestamp = ldt.toInstant(ZoneOffset.ofHours(8)).toEpochMilli();
long timestamp = ldt.toInstant(ZoneOffset.of("+08:00")).toEpochMilli();
long timestamp = ldt.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();
6、時區時間
// 時區ID的集合
Set<String> zoneSet = ZoneId.getAvailableZoneIds();
// 默認時區
ZoneId zoneId = ZoneId.systemDefault();
// 時區時間
LocalDateTime cur = LocalDateTime.now(); // 本地默認時間 2019-04-29T14:45:07.156
LocalDateTime ldt = LocalDateTime.now(ZoneId.of("America/Los_Angeles")); // 時區當前時間 2019-04-28T23:45:07.156
OffsetDateTime odt = OffsetDateTime.now(ZoneId.of("America/Los_Angeles")); // 帶偏移量時間 2019-04-28T23:45:07.156-07:00
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/Los_Angeles")); // 帶時區的時間 2019-04-28T23:45:07.156-07:00[America/Los_Angeles]
LocalDateTime ldto = odt.toLocalDateTime(); // 轉本地類時間 2019-04-28T23:45:07.156
LocalDateTime ldtz = zdt.toLocalDateTime(); // 轉本地類時間 2019-04-28T23:45:07.156
// 時鐘 類似時間戳
Clock clockDefault = Clock.systemDefaultZone(); //系統默認
Clock clockUtc = Clock.systemUTC(); // UTC
Clock c1ockZone = Clock.system(ZoneId.of("+08:00")); //指定時區
Clock clockRegion = Clock.system(ZoneId.of("Asia/Shanghai")); //指定區域
long timestamp = clockDefault.millis(); //獲取時間戳,等於System.currentTimeMillis()
===================================================
附:
1.DateFormat
DateFormat
根據當前語言環境格式化日期和時間。DateFormat
是一個抽象類,所以不能直接new創建實例對象。但該類爲我們提供了工廠方法方便我們使用。
getDateInstance()
方法,獲取格式化的日期,輸出樣式:2015-12-10
getDateTimeInstance()
方法,獲取格式化的日期和時間,輸出樣式:2015-12-10 10:21:41
getTimeInstance()
方法,獲取格式化的時間,輸出樣式:10:21:41
getInstance()
方法,獲取格式化的日期和時間,輸出樣式:15-12-10 上午10:21
也許你會發現,在這些工廠發放中允許我們傳入一個int參數,該參數允許我們設定格式化風格,從而得到我們相對理想的結果。下表中對應了不同的style值和輸出樣式(這些常量值都在DateFormat類中)
當然你也可以指定語言環境獲取該語言環境下的格式化日期和時間
DateFormat format = DateFormat.getDateInstance(DateFormat.DEFAULT,Locale.CANADA);//獲取加拿大的格式化日期
2.SimpleDateFormat
SimpleDateFormat
是DateFormat
的一個具體類,它允許我們指定格式模式從而獲取我們理想的格式化日期和時間。
通過SimpleDateFormat
的構造方法你可以傳入一個格式模式字符串或者通過applyPattern(String pattern)
方法添加一個格式模式字符串。
對於格式模式字符串,API爲我們提供了豐富的模式元素,下面列出幾個常用的模式元素
如果你設置Locale的話,會有不同的顯示格式,比如如果設置Locale.ENGLISH,E會顯示爲英文格式,a顯示爲AM或PM
Date date = new Date();
SimpleDateFormat format = new SimpleDateFormat("今天是yyyy-MM-dd E hh:mm:ss,是yyyy年的第DD天,在該月是第dd天");
System.out.println(format.format(date));
將會輸出:今天是2015-12-10 星期四 09:38:16,是2015年的第344天,在該月是第10天