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
// 取本月最後一天,再也不用計算是28,29,30還是31:
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2014-12-31
// 取下一天:
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 變成了2015-01-01
// 取2015年1月第一個週一,這個計算用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,不然會報錯。
- 這就是我總結的知識點,算是入個門,能解決正常的使用。如有錯誤,還望指出,及時更正。與君共勉。