概念
時區
不同時區在同一時刻,它們的本地時間是不同的,全球一共有24個時區,我們把倫敦所在的時區稱為標準時區,其他時區按照東西偏移的小時來區分,北京所在的時區是東八區(GMT+08:00)。
時區的表現方式如下:
- GMT+08:00
- UTC+08:00
- CST(China Standard Time / Central Standard Time USA)
- Asia/Shanghai
地區
Local 表示一個國家或地區的日期、時間、數字、貨幣等格式
- zh_CN: 表示的是中國的Local,日期用年月日表示2020-07-05
- en_US: 表示的是美國的Local,日期用日月年表示05/07/2020
計算機用Local在日期、時間、貨幣和字串之間進行轉換
中國使用者 | 美國使用者 | |
---|---|---|
購買價格: | 12000.0 | 12,000.00 |
購買日期: | 2020-07-05 | 05/07/2020 |
java.time的API
java.time提供了新的日期和時間API
- LocalDate/LocalTime/LocalDateTime
- ZonedDateTime/ZoneId
- Instant
- Formatter
- ...
新API的特點:
- 嚴格區分日期、時間
- 不變類(類似String)
- Month範圍1~12(Jan~Dec)
- Week範圍1~7(Mon~Sun)
LocalDateTime
LocalDate d = LocalDate.now(); // 當前日期
LocalTime t = LocalTime.now(); //當前時間
LocalDateTime dt = LocalDateTime.now(); // 當前日期時間
System.out.println(dt); // 嚴格按照ISO 8601格式列印 2020-07-05T16:38:37.356
//指定日期和時間
LocalDate d2 = LocalDate.of(2020, 7, 5); // 2020-07-05,注意 7=7月
LocalTime t2 = LocalTime.of(16, 38, 37); // 16:38:37
LocalDateTime dt2 = LocalDateTime.of(2020, 7, 5,16, 38, 37); // 2020-07-05T16:38:37
LocalDateTime dt3 = LocalDateTime.of(d2, t2); // 2020-07-05T16:38:37
//對日期進行格式化a
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(dtf.format(LocalDateTime.now())); // 2020-07-05 16:45:08
//將字串解析成日期
LocalDateTime parse = LocalDateTime.parse("2020-07-05 16:45:08", dtf);
System.out.println(parse); // 2020-07-05T16:45:08
新的DateTimeFormatter是不可變的。預設情況下,LocalDate,LocalTime,LocalDateTime按照ISO標準格式化和解析:
- yyyy-MM-dd
- HH:mm:ss
- HH:mm:ss:SSS
- yyyy-MM-dd'T'HH:mm:ss
- yyyy-MM-dd'T'HH:mm:ss:SSS
重大更新:對日期和時間進行加減
- plusDays() 在現在的日期加上具體天數
- minusHous() 在現在的時間減去具體的小時
- plusWeeks() 在現在的日期時間加上具體的週數
// +5 天
LocalDate today = LocalDate.now();
LocalDate after5Days = today.plusDays(5);
System.out.println(after5Days); //2020-07-10
// -2小時
LocalTime now = LocalTime.now();
LocalTime before2Hours = now.minusHours(2);
System.out.println(before2Hours); // 14:59:22.526
// +1月-2周
LocalDate date = today.plusMonths(1).minusWeeks(2);
System.out.println(date); // 2020-07-22
對日期和時間進行調整:
- withDayOfMonth()
- withMonth()
- withHour()
- ...
- with()
//本月第一天
LocalDate firstDay = LocalDate.now().withDayOfMonth(1);
System.out.println(firstDay); // 2020-07-01
//把秒和納秒調整為0
LocalTime at = LocalTime.now().withSecond(0).withNano(0);
System.out.println(at); // 17:08
//本月最後一天
LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
System.out.println(lastDay); // 2020-07-31
//本月第一個週日
LocalDate firstSunday = LocalDate.now().with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY));
System.out.println(firstSunday); //2020-07-05
判斷日期和時間的先後:
- isBefore()
- isAfter()
- equals()
LocalDate d01 = LocalDate.of(2020,7,5);
LocalDate d02 = LocalDate.of(2020,7,4);
System.out.println(d01.isBefore(d02)); // false
System.out.println(d01.isAfter(d02)); // true
計算日期的Period: 某一天到指定的某一天具體相差多久
- getYears()
- getMonths()
- getDays()
LocalDate d03 = LocalDate.of(2020,7,5);
LocalDate d04 = LocalDate.of(2018,3,28);
//通過until()方法獲取Period物件,判斷兩個日期相差?年?月?天
Period period = d03.until(d04);
System.out.println(period); // P-2Y-3M-8D 表示2020年7月5日到2018年3月28日中相差 2年3個月8天
//兩個日期一共相差多少天?
long day01 = LocalDate.of(2020, 7, 5).toEpochDay();
long day02 = LocalDate.of(2018,3,28).toEpochDay();
System.out.println(day01-day02); // 830
LocalDateTime無法與long進行轉換
- 因為LocalDateTime 沒有時區,無法確定某一時刻
- ZonedDateTime 有時區,可以與long進行轉換
ZonedDateTime
ZonedDateTime = LocalDateTime + ZoneId
- ZonedDateTime: 帶時區的日期和時間
- ZoneId: 新的時區物件(取代舊的java.util.TimeZone)
- Instant: 時刻物件(epoch seconds)
ZonedDateTime zbj = ZonedDateTime.now(); // 當前時區的日期和時間
System.out.println(zbj); // 2020-07-05T17:32:40.415+08:00[Asia/Shanghai]
ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York")); // 紐約時區的當前日期和時間
System.out.println(zny); // 2020-07-05T05:34:29.522-04:00[America/New_York]
ZonedDateTime可以從LocalDateTime轉換: atZone()
//關聯到當前預設時區
ZonedDateTime bj = ldt.atZone(ZoneId.systemDefault());
System.out.println(bj); // 2020-07-05T17:36:12+08:00[Asia/Shanghai]
//關聯到紐約時區
ZonedDateTime ny = ldt.atZone(ZoneId.of("America/New_York"));
System.out.println(ny); // 2020-07-05T17:36:12-04:00[America/New_York]
轉換時區:withZoneSamleInstant()
LocalDateTime ldt = LocalDateTime.of(2020, 7, 5, 17, 36, 12);
//關聯到當前預設時區
ZonedDateTime bj = ldt.atZone(ZoneId.systemDefault());
System.out.println(bj); // 2020-07-05T17:36:12+08:00[Asia/Shanghai]
// 轉換到紐約時區
ZonedDateTime zdt = bj.withZoneSameInstant(ZoneId.of("America/New_York"));
System.out.println(zdt); // 2020-07-05T17:36:12-04:00[America/New_York]
Instant物件表示時刻:
- ZonedDateTime.toInstant()
- Instant.getEpochSecond()
Instant ins = Instant.now();
Instant ins2 = ZonedDateTime.now().toInstant();
ZonedDateTime zdt = ins.atZone(ZoneId.of("Z"));
//注意是秒
long epoch = ins.getEpochSecond();
如果專案中需要使用generatorConfig.xml配置檔案生成java8中的日期型別LocalDate、LocalTime、LocalDateTime等等,需要在配置檔案中的javaTypeResolver結點中加入屬性useJSR310Types,當useJSR310Types為true時,就會jdbc對應的日期型別會轉成java8中的LocateDateTime型別,如果useJSR310Types為false,則還是轉成java.util.Date型別。
<javaTypeResolver>
<property name="useJSR310Types" value="true"/>
</javaTypeResolver>
一旦mybatis中使用了java8中的日期型別,記得要在專案中引入mybatis-typehandlers-jsr310,這個主要是處理java8中的日期型別。
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-typehandlers-jsr310</artifactId>
<version>1.0.2</version>
</dependency>
注意:用maven mybatis外掛如果不在plugin裡面新增依賴包的引用的話,會找不到相關得jar包,在plugin外部得jar包,他不會去找到並執行,所以要把plugin執行依賴得jar配置都放在裡面,pom.xml配置 mybatis外掛如下:
<plugins>
<plugin>
<groupId>org.mybatis.generator</groupId>
<artifactId>mybatis-generator-maven-plugin</artifactId>
<version>1.3.7</version>
<dependencies>
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.13</version>
</dependency>
</dependencies>
</plugin>
</plugins>
注意,在連線mysql8.0的時候要指明timeZone,即serverTimezone=UTC這個不能忘