1. 程式人生 > >JDK8中好用的日期處理-LocalDate類-LocalTime-LocalDateTIme,mysql解決時區相差13小時的問題,日期格式器DateTimeFormatter

JDK8中好用的日期處理-LocalDate類-LocalTime-LocalDateTIme,mysql解決時區相差13小時的問題,日期格式器DateTimeFormatter

介紹

LocalDate是一種更為高效的日期類,比起Date的複雜具有相當高的簡潔性,吸取了企業級別的joda.time時間處理的優點,避免了傳統的Date和Calendar複合起來計算的難處

LocalDate

寫在最前面
兩個特性務必記住!!!!

  • 執行緒安全
  • 所有修改返回皆為新物件,對之前的物件沒有影響

示例程式碼:

package LocalDate;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.List;

package LocalDate;

import java.time.LocalDate;
import
java.util.ArrayList; import java.util.List; public class Demo3 { private LocalDate localDate = LocalDate.now(); private List<Integer> list = new ArrayList<>(); public void change() { localDate.plusDays(1); list.add(1); } public static void main(String[] args) { Demo3 demo3 = new
Demo3(); Runnable runnable = demo3::change; List<Thread> list = new ArrayList<>(); for (int i = 0; i < 50; i++) { list.add(new Thread(runnable)); } for (Thread thread : list) { thread.start(); } try { Thread.sleep(3000
); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(demo3.list.size()); System.out.println(demo3.localDate); } } --------結果------- 49 2018-07-30

分析:

  • 為了讓結果更清楚這裡用了list作為比較,筆者實驗的日期就是7.30,結果localDate本身並沒有改變還是7.30,可以看出,所有的修改不是在原來的物件上進行更改,而是new出了新的物件。這點得以證明
  • 執行緒安全:由於是new出新物件,就不存在對同一資源的存取這個競爭條件,沒有了競爭條件,自然不存線上程安不安全的問題,list50次是對同一個物件進行存取,所以會出現執行緒安全問題。這麼一對比就能知曉了。官方也指出了它的執行緒安全性,此處只是取一個方法試試看。
  • 注意:不可以再賦值比如localDate=localDate.plusDays(1); 如果這樣就人為地加入了賦值這個操作,就不能夠準確檢測出方法的執行緒安全性。

常用API:
這裡寫圖片描述

localTime

與LocalDate相似:
這裡寫圖片描述

日期更改

涉及到日期的更改就需要另一個強大的類:TemporalAdjusters
這裡寫圖片描述
相關API檢視文件即可,不多。

簡單小例子

System.out.println("今天的日期是" + today);
System.out.println("上週的星期一為:" + today.minusWeeks(1).with(DayOfWeek.MONDAY));
System.out.println("下個月的第二個週一的時間為:" + today.plusMonths(1).with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.MONDAY)));

--------輸出--------
今天的日期是2018-07-30
上週的星期一為:2018-07-23
下個月的第二個週一的時間為:2018-08-13

// 取當前日期:
LocalDate today = LocalDate.now(); // -> 2014-12-24
// 根據年月日取日期,12月就是12:
LocalDate crischristmas = LocalDate.of(2014, 12, 25); // -> 2014-12-25
// 根據字串取:
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); // 嚴格按照ISO yyyy-MM-dd驗證,02寫成2都不行,當然也有一個過載方法允許自己定義格式
LocalDate.parse("2014-02-29"); // 無效日期無法通過:DateTimeParseException: Invalid date

// 取本月第1天:
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2014-12-01
// 取本月第2天:
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2014-12-02
// 取本月最後一天,再也不用計算是282930還是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2014-12-31
// 取下一天:
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 變成了2015-01-01
// 取20151月第一個週一,這個計算用Calendar要死掉很多腦細胞:
LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2015-01-05

例子來自於廖雪峰老師的。
這裡寫圖片描述

和sql對應的關係

SQL -> Java

date -> LocalDate
time -> LocalTime
timestamp -> LocalDateTime

實戰:jdbc連線

示例:

LocalDateTime nowTime = LocalDateTime.now();
Connection connection = null;
PreparedStatement statement = null;

try {
    String url = "jdbc:mysql://localhost:3306/laboratory?timeZone=TMC&useSSL=true";
    String user = "root";
    String password = "lyy1314520";
    // 載入驅動
    Class.forName("com.mysql.cj.jdbc.Driver");

    //獲取連線
    connection = DriverManager.getConnection(url, user, password);

    String sql = "insert into time(time) values(?)";
    //獲取statement物件
    statement = connection.prepareStatement(sql);
    statement.setTimestamp(1, Timestamp.valueOf(nowTime));

    // 執行sql語句
    statement.executeUpdate();
} catch (Exception e) {
    e.printStackTrace();
} finally {
    if (statement!=null){
        try {
            statement.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
    if (connection != null){
        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
  }

發現問題:儲存在資料庫的時間少了13個小時,搜尋資料後,原來是時區不對,只需要在命令列視窗輸入這樣的兩條程式碼設定時區即可。預設是使用系統的。

set global time_zone='+08:00';
set time_zone = '+08:00';

show variables like '%time_zone:'
這裡寫圖片描述

再次執行程式碼,插入準確時間。

準確插入時間圖:
這裡寫圖片描述
附上,TimeStamp->LocalDateTime方法:

LocalDateTime localDateTime = time.toLocalDateTime();

格式轉換

介紹:
說到轉換格式,有SimpleDateFormat和DateFormat,但是它們兩者都是執行緒不安全的!啥情況下會有這樣的問題呢?如果我們為了實現日期轉換這樣的工具,每次都new一個物件,但是用完了就不用了,就造成了浪費,為此我們會將它寫成單例的,但是單例的同時,一個物件供多個執行緒使用的時候,就會出現執行緒安全的問題。這個時候就需要這個新的jdk8出的DateTimeformatter這個類。

字串->類

寫在前面。如果是很工整的格式,yyyy-MM-dd 這種日期格式字串,直接用LocalDate.parse()進行轉換就行了,相對應的時間也是。既有時間又有日期的用DateTimeformatte這個類就行。
示例:

String time = "1997-01-31 18:39:20";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime =LocalDateTime.from(formatter.parse(time));

或者:
String time = "1997-01-31 18:39:20";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dateTime = LocalDateTime.parse(time,formatter);

類->字串

  • 如果是LocalDate這種標準格式的,直接toString就可以了,-
  • 如果是LocalTime這種格式的,toString會附帶納秒值21:06:30.760163
    這個時候你可以使用日期格式器,或者這樣
    LocalTime time1 = LocalTime.now().withNano(0),把納秒直接清0.
  • 如果是LocalDateTime,這個時候是需要一個日期轉換器的。才能由時間+日期->想要的時間,
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime nowTime = LocalDateTime.now();
String result = nowTime.format(formatter);

附上一張字元轉換表,個人習慣這種字母的,不喜歡系統設定的這些常量。

  Symbol  Meaning                     Presentation      Examples
  ------  -------                     ------------      -------
   G       era                         text              AD; Anno Domini; A
   u       year                        year              2004; 04
   y       year-of-era                 year              2004; 04
   D       day-of-year                 number            189
   M/L     month-of-year               number/text       7; 07; Jul; July; J
   d       day-of-month                number            10

   Q/q     quarter-of-year             number/text       3; 03; Q3; 3rd quarter
   Y       week-based-year             year              1996; 96
   w       week-of-week-based-year     number            27
   W       week-of-month               number            4
   E       day-of-week                 text              Tue; Tuesday; T
   e/c     localized day-of-week       number/text       2; 02; Tue; Tuesday; T
   F       week-of-month               number            3

   a       am-pm-of-day                text              PM
   h       clock-hour-of-am-pm (1-12)  number            12
   K       hour-of-am-pm (0-11)        number            0
   k       clock-hour-of-am-pm (1-24)  number            0

   H       hour-of-day (0-23)          number            0
   m       minute-of-hour              number            30
   s       second-of-minute            number            55
   S       fraction-of-second          fraction          978
   A       milli-of-day                number            1234
   n       nano-of-second              number            987654321
   N       nano-of-day                 number            1234000000

   V       time-zone ID                zone-id           America/Los_Angeles; Z; -08:30
   z       time-zone name              zone-name         Pacific Standard Time; PST
   O       localized zone-offset       offset-O          GMT+8; GMT+08:00; UTC-08:00;
   X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
   x       zone-offset                 offset-x          +0000; -08; -0830; -08:30; -083015; -08:30:15;
   Z       zone-offset                 offset-Z          +0000; -0800; -08:00;

   p       pad next                    pad modifier      1

   '       escape for text             delimiter
   ''      single quote                literal           '
   [       optional section start
   ]       optional section end
   #       reserved for future use
   {       reserved for future use
   }       reserved for future use

總結

這次主要學習了jdk8的日期LocalDate簡單入門,總結如下:

  • LocalDate日期是一個便於使用的日期類,執行緒安全,Date類比較複雜,時間計算麻煩。
  • DateTimeFormatter的使用也安全,方便。以後用它來代替SimpleDateFormat
  • JDBC的TimeStamp類和LocalDateTime的轉換也很方便,提供了相應的方法。
  • 使用的時候,日期必須是標準的yyyy-MM-dd格式,比如1月必須寫成01,不然會報錯。
  • 這就是我總結的知識點,算是入個門,能解決正常的使用。如有錯誤,還望指出,及時更正。與君共勉。