java8日期時間API
爲什麼要使用java8的日期時間API,因爲以前用的Date,Calendar都是線程不安全的!
- 演示線程不安全
public class TestSimpleDateFormat {
/**
* 使用之前的時間API,會發生線程不安全的問題
* java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points
* @throws Exception
*/
@Test
public void test() throws Exception {
//創建線程池
ExecutorService pool = Executors.newFixedThreadPool(10);
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd");
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return sdf.parse("2020/06/15");//Mon Jun 15 00:00:00 GMT+08:00 2020
}
};
//定義一個集合來裝時間!
List<Future<Date>> list = new ArrayList<>();
for(int i=0; i<10; i++){
list.add(pool.submit(task));
}
for(Future<Date> future:list){
System.out.println(future.get());
}
//關閉線程池
pool.shutdown();
}
/**
* 使用ThreadLocal來進行改進
*/
@Test
public void test2()throws Exception{
//創建線程池
ExecutorService pool = Executors.newFixedThreadPool(10);
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return TestSimpleDateFormat2.convert("2020/06/15");//Mon Jun 15 00:00:00 GMT+08:00 2020
}
};
//定義一個集合來裝時間!
List<Future<Date>> list = new ArrayList<>();
for(int i=0; i<10; i++){
list.add(pool.submit(task));
}
for(Future<Date> future:list){
System.out.println(future.get()); // Mon Jun 15 00:00:00 GMT+08:00 2020
}
//關閉線程池
pool.shutdown();
}
/**
* java8新的時間API改進!
* LocalDate
* @throws Exception
*/
@Test
public void test3()throws Exception{
//創建線程池
ExecutorService pool = Executors.newFixedThreadPool(10);
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("2020/06/15",dateTimeFormatter);
}
};
//定義一個集合來裝時間!
List<Future<LocalDate>> list = new ArrayList<>();
for(int i=0; i<10; i++){
list.add(pool.submit(task));
}
for(Future<LocalDate> future:list){
System.out.println(future.get()); //2020-06-15
}
//關閉線程池
pool.shutdown();
}
}
上面test2()方法中的輔助類
/**
* 使用ThreadLocal來進行改進
*/
public class TestSimpleDateFormat2 {
private static ThreadLocal<DateFormat> threadLocal = new ThreadLocal<DateFormat>(){
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy/MM/dd");
}
};
public static Date convert(String source) throws Exception {
return threadLocal.get().parse(source);
}
}
LocalDateTime
,Instant
,Duration
,Period
public class TestLocalDateTime {
//1. LocalDateTime, LocalDate, LocalTime:人讀的時間
@Test
public void test1(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2020-06-16T07:42:45.330
LocalDateTime ldt2 = LocalDateTime.of(2020, 06, 16, 07, 44, 44);
System.out.println(ldt2); //2020-06-16T07:44:44
LocalDateTime ldt3 = ldt.plusYears(2);//加2年,
System.out.println(ldt3);//2022-06-16T07:46:34.174
LocalDateTime ldt4 = ldt.minusDays(2);//減2天
System.out.println(ldt4);//2020-06-14T07:46:34.174
//單獨獲取年月日,時分秒
System.out.println(ldt.getYear()+"年");
System.out.println(ldt.getMonthValue()+"月");
System.out.println(ldt.getDayOfMonth()+"日");
System.out.println(ldt.getHour()+"時");
System.out.println(ldt.getMinute()+"分");
System.out.println(ldt.getSecond()+"秒");
}
//2. Instant: 時間戳(以Unix元年: 1970年1月1日 00:00:00到某個時間之間的毫秒值!)
@Test
public void test2(){
Instant ins1 = Instant.now();// 默認獲取UTC時區
System.out.println(ins1); //2020-06-15T23:52:31.319Z
//上面打印的時間跟現在的時間不符,因爲我們在東八區,所以得加8個時區
OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);//2020-06-16T07:54:30.292+08:00
//獲取秒
System.out.println(ins1.getEpochSecond());
//獲取毫秒值
System.out.println(ins1.toEpochMilli());
Instant instant = Instant.ofEpochSecond(60);
System.out.println(instant); //1970-01-01T00:01:00Z
}
/**
* 計算“時間”之間的間隔!!: Duration
*/
@Test
public void test3(){
Instant instant1 = Instant.now();
try {
Thread.sleep(1000); //間隔1秒
} catch (InterruptedException e) {
}
Instant instant2 = Instant.now();
Duration duration = Duration.between(instant1, instant2);
System.out.println(duration);//PT1S
System.out.println("間隔:"+duration.getSeconds()+"秒");
System.out.println("=================================");
LocalTime localTime = LocalTime.now();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
LocalTime localTime2 = LocalTime.now();
Duration duration2 = Duration.between(localTime, localTime2);
System.out.println(duration2);
System.out.println("間隔"+duration2.getSeconds()+"秒");
}
/**
* 計算“日期”之間的間隔!
*/
@Test
public void test4(){
LocalDate localDate = LocalDate.now(); //2020/6/16
LocalDate localDate2 = LocalDate.of(2022,6,16);
Period period = Period.between(localDate, localDate2);
System.out.println(period); //P2Y
System.out.println(period.getYears()); //2
System.out.println(period.getMonths());//0
System.out.println(period.getDays());//0
}
}
TemporalAdjuster
DateTimeFormatter
public class TestTemporaAdjuster {
/**
* TemporaAdjuster(函數式接口): 時間校正器
* LocalDateTime,LocalDate,LocalTime: 實現了該接口!
*/
@Test
public void test(){
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt); //2020-06-16T20:59:19.763
LocalDateTime ldt2 = ldt.withDayOfMonth(10);
System.out.println(ldt2); //2020-06-10T20:59:19.763
//下一個星期天!
LocalDateTime ldt3 = ldt.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(ldt3);//2020-06-21T21:01:11.733
//自定義:下一個工作日
// ldt.with(new TemporalAdjuster() {
// @Override
// public Temporal adjustInto(Temporal temporal) {
// return null;
// }
// });
//lambda表達式
LocalDateTime ldt5 = ldt.with(temporal -> {
LocalDateTime ldt4 = (LocalDateTime) temporal;
DayOfWeek dayOfWeek = ldt4.getDayOfWeek();
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return ldt4.plusDays(3); //如果是星期五,加三天就是下一個工作日(星期一)
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return ldt4.plusDays(2);
} else {
return ldt4.plusDays(1); //其他星期天~星期4,加一天也還是工作日!
}
});
System.out.println("下一個工作日:"+ldt5);
}
/**
* 格式化:日期(Date)時間(Time)
*/
@Test
public void test2(){
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
LocalDateTime ldt = LocalDateTime.now();
//將時間 -> 格式化成字符串
String format = dtf.format(ldt);
System.out.println(format); // 2020年06月16日 21:27:37
//字符串 -> 時間
LocalDateTime ldt2 = ldt.parse(format,dtf); //要格式化哪種時間!
System.out.println(ldt2); //2020-06-16T21:31:10
}
}