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
}
}