Java 8 中新的時間與日期 API 中的全部類都是不可變且線程安全的,任何修改操做都會返回一個新的實例,而以前 java.util.Date、Calendar 以及 SimpleDateFormat 這些關鍵的類都不是線程安全的。java
java 8 對 時間api 從新進行了設計,經常使用的有如下幾種類。api
/*** * LocalDate:表示不帶時間的日期 * LocalTime:表示不帶日期的時間 * LocalDateTime:日期和時間類 * ZoneId:時區 * ZonedDateTime:一個帶時區的完整時間 * Instant:Unix 時間,它表明的是時間戳,好比 2018-01-14T02:20:13.592Z * Clock:獲取某個時區下當前的瞬時時間,日期或者時間 * Duration:表示一個絕對的精確跨度,使用毫秒爲單位 * Period:這個類表示與 Duration 相同的概念,可是以人們比較熟悉的單位表示,好比年、月、周 * DateTimeFormatter:格式化輸出 * TemporalAdjusters:得到指定日期時間等,如當月的第一天、今年的最後一天等 * */
方法安全
/** * of:靜態工廠方法,用於建立實例 * now:靜態工廠方法,用當前時間建立實例 * parse:靜態工廠方法,從字符串解析獲得對象實例 * get:獲取時間日期對象的部分狀態。 * is:檢查某些東西的是不是 true,例如比較時間先後 * with:返回一個部分狀態改變了的時間日期對象拷貝 * plus:返回一個時間增長了的、時間日期對象拷貝 * minus:返回一個時間減小了的、時間日期對象拷貝 * to:轉換到另外一個類型 * at:把這個對象與另外一個對象組合起來,例如 date.atTime(time) * format:提供格式化時間日期對象的能力 * */
/** *LocalDate */ //LocalDate 是用來表示無時間的日期的,也不附帶任何與時區相關的信息 LocalDate today = LocalDate.now(); System.out.println("今日日期:"+ today); //它提供 plus()/minus() 方法能夠用來增長減小日、星期或者月,ChronoUnit 則用來表示這個時間單位。 // 這些方法返回的是一個新的 LocalDate 實例的引用,由於 LocalTime 是不可變的, // 任何修改操做都會返回一個新的實例。 LocalDate localDate = today.plusDays(1); //等價於 today.plus(1, ChronoUnit.DAYS); System.out.println("明日日期:"+ localDate); //日期減法 LocalDate today1 = localDate.minus(1, ChronoUnit.DAYS); System.out.println("今日日期:" + today1);
LocalTime time = LocalTime.now(); System.out.println("如今的時間:" + time); //小時 int hour = time.getHour(); System.out.println(hour); OffsetTime offsetTime = time.atOffset(ZoneOffset.UTC); System.out.println("UTC時間: "+offsetTime); /** * */ //系統默認時間 LocalTime time2 = LocalTime.now(Clock.systemDefaultZone()); System.out.println("系統默認時間 : "+time2); LocalDate date =LocalDate.now(); //LocalDateTime 將 LocalDate 和 LocalTime 結合起來 LocalDateTime localDateTime = LocalDateTime.of(today,time2); System.out.println("LocalDateTime 將 LocalDate 和 LocalTime 結合起來 : " + localDateTime); // LocalDate localDate1 = LocalDate.of(2018, 11, 11); System.out.println("localDate1 自定義日期: " + localDate1); LocalTime localTime2 = LocalTime.of(12, 11, 11); LocalTime localTime3 = LocalTime.of(12, 12, 12, 12); System.out.println("LocalTime 自定義時間: " + localTime2); System.out.println("LocalTime 自定義時間帶納秒: " + localTime3);
格式化與解析時間對象 DateTimeFormatter 格式器用於解析日期字符串和格式化日期輸出, 建立格式器最簡單的方法是經過 DateTimeFormatter 的靜態工廠方法以及常量。
//1 自定義字母模式解析 DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd"); String format = localDate1.format(dateTimeFormatter); System.out.println(format); //2 經常使用 ISO 格式常量,如 ISO_LOCAL_DATE dateTimeFormatter = DateTimeFormatter.ISO_DATE; format = localDate1.format(dateTimeFormatter); System.out.println(format); //3 本地化樣式,如 ofLocalizedDate(FormatStyle.MEDIUM) dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL); format = localDate1.format(dateTimeFormatter); System.out.println("FormatStyle.FULL = "+ format);//2018年11月11日 星期日 dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM); format = localDate1.format(dateTimeFormatter); System.out.println("FormatStyle.MEDIUM = " + format);//2018-11-11 dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG); format = localDate1.format(dateTimeFormatter); System.out.println("FormatStyle.LONG = "+ format);//2018-11-11 //將日期格式化指定格式 String format1 = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy,MM,dd")); System.out.println(format1);//2019,08,25
字符串格式化成日期app
LocalDate parse = LocalDate.parse("2019-10-10"); System.out.println("默認: " + parse); //parse = LocalDate.parse("2019/8/10");//異常 /** 默認的解析格式是 - * public static final DateTimeFormatter ISO_LOCAL_DATE; * static { * ISO_LOCAL_DATE = new DateTimeFormatterBuilder() * .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD) * .appendLiteral('-') * .appendValue(MONTH_OF_YEAR, 2) * .appendLiteral('-') * .appendValue(DAY_OF_MONTH, 2) * .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE); * } */ //System.out.println("默認: " + parse); //因此對於 "2019/8/10" 格式 咱們須要自定義 解析格式 //注意 2019/08/10 不能寫成 2019/8/10 ,否則會拋出異常 parse = LocalDate.parse("2019/08/10",DateTimeFormatter.ofPattern("yyyy/MM/dd")); System.out.println(parse); //2019-08-10 //自定義解析格式 dates = LocalDate.parse("20190825", DateTimeFormatter.ofPattern("yyyyMMdd")); System.out.println(dates);//2019-08-25 dates = LocalDate.parse("2019/08/25", DateTimeFormatter.ofPattern("yyyy/MM/dd")); System.out.println(dates);//2019-08-25 // 25/08/2019 - > 2019/08/25 LocalDate parse2 = LocalDate.parse("25/08/2019",DateTimeFormatter.ofPattern("dd/MM/yyyy")); String format2 = parse2.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")); System.out.println(format2);//2019/08/25 LocalDate parse2 = LocalDate.parse("25/08/2019",DateTimeFormatter.ofPattern("dd/MM/yyyy")); System.out.println(parse2);//2019-08-25
Duration 表示一個時間段,Duration 包含兩部分:seconds 表示秒,nanos 表示納秒,它們的組合表達了時間長度。 由於 Duration 表示時間段,因此 Duration 類中不包含 now() 靜態方法。注意,Duration 不包含毫秒這個屬性。
LocalDateTime from =LocalDateTime.of(2019,8,11,11,11,11,11); LocalDateTime to =LocalDateTime.of(2019,8,10,10,10,10,10); Duration between = Duration.between(from, to); long l = between.toDays(); System.out.println("相差天數= " + l); // -1 long l1 = between.toHours(); System.out.println(l);// -1 long l2 = between.toMinutes(); System.out.println(l);// -1 long l3 = between.toMillis(); System.out.println(l);// -1 long l4 = between.toNanos(); System.out.println(l);// -1
Period 在概念上和 Duration 相似,區別在於 Period 是以年月日來衡量一個時間段。
Duration 用於計算兩個時間間隔,Period 用於計算兩個日期間隔,因此 between() 方法只能接收 LocalDate 類型的參數。ui
Period of1 = Period.of(2019, 10, 10); Period of2 = Period.of(2018, 9, 9); System.out.println(of1);//P2019Y10M10D LocalDate from1 =LocalDate.of(2019,8,11); LocalDate to2 =LocalDate.of(2018,8,10); Period between1 = Period.between(from1, to2); //Period 獲得的是差值的絕對值 System.out.println("相差年 : " + between1.getYears());//-1 System.out.println("相差月 : " + between1.getMonths());//0 System.out.println("相差日 : " + between1.getDays());//-1 //計算兩個時間的區間距離呢 long year = from1.until(to2, ChronoUnit.YEARS);//-1 long month = from1.until(to2, ChronoUnit.MONTHS);//-12 long month1 = to2.until(from1, ChronoUnit.MONTHS);//12 System.out.println(year); System.out.println(month); System.out.println("正值 " + month1);
//加1s Instant instant1 = Instant.ofEpochSecond(1); System.out.println(instant1);//1970-01-01T00:00:01Z //加10毫秒 Instant instant2 = Instant.ofEpochMilli(10); System.out.println(instant2);//1970-01-01T00:00:00.010Z //當前時間 從1970-1-1號到如今的時間 至關於new Date() Instant instant = Instant.now(); //秒 = 2019-08-24T14:49:36.344Z System.out.println(" 秒 = " + instant); //new Date()轉爲Instant Instant instant3 = new Date().toInstant(); System.out.println(" 與new Date()轉換 " + instant3);//2019-08-24T14:57:07.464Z //解析時間 Instant parse1 = Instant.parse("2019-08-24T14:59:16.708Z"); System.out.println(parse1); //加10天 Instant plus = parse1.plus(10, ChronoUnit.DAYS); //2019-09-03T14:59:16.708Z System.out.println(plus);
Clock 是時鐘系統,用於查找當前時刻。 你能夠用它來獲取某個時區下當前的日期或者時間。能夠用 Clock 來替代舊的 System.currentTimeInMillis() 與 TimeZone.getDefault() 方法。
//世界協調時UTC Clock clock = Clock.systemUTC(); System.out.println(clock.getZone());// time-zone Z //獲取clock對應的毫秒數,與System.currentTimeMillis()輸出相同 System.out.println(clock.millis());// //經過Clock獲取當前時刻 System.out.println("經過Clock獲取當前時刻 " + clock.instant());// //默認時區時間 Clock clock1 = Clock.systemDefaultZone(); System.out.println(clock1.instant()); //自定義時區 Clock clock2 = clock1.withZone(ZoneId.of("Asia/Shanghai")); Instant instant4 = clock2.instant(); System.out.println(instant4); //紐約時間 Clock clock3 = Clock.system(ZoneId.of("America/New_York")); System.out.println("紐約時間: " + LocalDateTime.now(clock3)); //不能用 .instant() 輸出 此輸出是系統默認時間 //System.out.println(clock3.instant()); //當前時區加上 100s Clock offset = Clock.offset(clock, Duration.ofSeconds(100)); System.out.println(offset.instant());
//默認時區時間 ZonedDateTime now = ZonedDateTime.now(); LocalDate localDate2 = now.toLocalDate(); System.out.println(localDate2);//2019-08-24 //特定時區下的日期和時間 ZonedDateTime Shanghai = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Asia/Shanghai")); System.out.println(Shanghai);//2019-08-24T23:22:31.149+08:00[Asia/Shanghai] ZonedDateTime Tokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo")); System.out.println(Tokyo);//2019-08-25T00:26:51.690+09:00[Asia/Tokyo] ZoneId america = ZoneId.of("America/New_York"); System.out.println(ZonedDateTime.now(america));//2019-08-24T11:28:48.430-04:00[America/New_York]
有的時候,你須要進行一些更加複雜的日期操做,好比,將日期調整到下個週日、下個工做日,或者是本月的最後一天。這時,你可使用重載版本的withXXX方法,向其傳遞一個提供了更多定製化選擇的TemporalAdjuster對象, 更加靈活地處理日期。對於最多見的用例,日期和時間API已經提供了大量預約義的 TemporalAdjuster。你能夠經過TemporalAdjuster類的靜態工廠方法訪問它們。
//當月中 第二週 的週一 TemporalAdjuster temporalAdjuster1 = TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.MONDAY); LocalDate with = LocalDate.now().with((temporal) -> temporal.with(temporalAdjuster1)); System.out.println(with);//2019-08-12 //firstDayOfMonth 當月的第一天 TemporalAdjuster temporalAdjuster2 = TemporalAdjusters.firstDayOfMonth(); with = LocalDate.now().with((temporal) -> temporal.with(temporalAdjuster2)); System.out.println(with);//2019-08-1 //firstDayOfNextYear 明年的第一天 System.out.println(LocalDate.now().with((temporal -> temporal.with(TemporalAdjusters.firstDayOfNextYear()))));//2020-01-01 /** * nextOrSame/previousOrSame 建立一個新的日期, * 並將其值設定爲日期調整後或者調整前,第一個符合指定星 期幾要求的日期,若是該日期已經符合要求,直接返回該對象 */ //今天是2019-08-25 週日 下一個週一 返回2019-08-26 System.out.println(LocalDate.now().with((temporal -> temporal.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY)))));//2020-01-01 //返回下一個第一個知足的指定日期 也就是 週四 第一個是 2019-08-29 第二個是 2019-09-05 可是返回一個知足的。 System.out.println(LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.THURSDAY)));//2019-08-29
Date date1 = new Date(); System.out.println("current date: " + date1); ZonedDateTime zonedDateTime = date1.toInstant().atZone(ZoneId.systemDefault()); //Date -> LocalDate LocalDate localDate31 = zonedDateTime.toLocalDate(); System.out.println(localDate31);//2019-08-24 //Date -> LocalDate ZonedDateTime zonedDateTime3 = date1.toInstant().atZone(ZoneId.of("Asia/Shanghai")); LocalDate localDate32 = zonedDateTime3.toLocalDate(); System.out.println(localDate32);//2019-08-24 //Date -> LocalDateTime LocalDateTime localDateTime1 = zonedDateTime.toLocalDateTime(); //Date -> LocalDateTime 另外一種方式 LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault()); //Date -> LocalTime LocalTime time1 = zonedDateTime.toLocalTime(); //Calendar --> Instant Calendar.getInstance().toInstant();
//LocalDateTime-> Date 方法 LocalDateTime localDateTime4 = LocalDateTime.now(); System.out.println("localDateTime: " + localDateTime4);//2019-08-24T23:44:23.274 //LocalDateTime-> Date 方法 Date from2 = Date.from(localDateTime4.toInstant(ZoneOffset.UTC)); Instant instant5 = from2.toInstant(); System.out.println(from2);//Sun Aug 25 07:44:23 CST 2019 System.out.println(instant5);//2019-08-24T23:44:23.274Z //// LocalDate -> Date LocalDate localDate3 = LocalDate.now(); //先把 LocalDate -> LocalDateTime LocalDateTime localDateTime3 = localDate3.atStartOfDay(); //再把 LocalDateTime -> Date Date from3 = Date.from(localDateTime3.toInstant(ZoneOffset.UTC)); System.out.println(from3);