目录
新的时间处理API
-
传统日期处理的方式线程不安全(多线程的环境下)
-
Java8的日期处理方式线程是安全的(多线程的环境下)
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
/**
* Java8之前的 日期处理方式(线程不安全) 多线程情况下会抛异常
*/
public class DateTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return dateFormat.parse("2018-12-12");
}
};
ExecutorService service = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(service.submit(task));
}
for (Future<Date> result : results) {
System.out.println(result.get());
}
service.shutdown();
}
}
Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: "11.E111E"
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at DateTest.main(DateTest.java:34)
Caused by: java.lang.NumberFormatException: For input string: "11.E111E"
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2043)
at sun.misc.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
at java.lang.Double.parseDouble(Double.java:538)
at java.text.DigitList.getDouble(DigitList.java:169)
at java.text.DecimalFormat.parse(DecimalFormat.java:2089)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1867)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at DateTest$1.call(DateTest.java:21)
at DateTest$1.call(DateTest.java:18)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)
解决办法:
传统方式
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class ThreadLocalDateFormat {
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyyMMdd");
}
};
public static Date convert(String source) throws ParseException {
return df.get().parse(source);
}
}
package time;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.*;
public class TimeTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
Callable<Date> task = new Callable<Date>() {
@Override
public Date call() throws Exception {
return ThreadLocalDateFormat.convert("20181020");
}
};
ExecutorService service = Executors.newFixedThreadPool(10);
List<Future<Date>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(service.submit(task));
}
for (Future<Date> result : results) {
System.out.println(result.get());
}
service.shutdown();
}
}
Java8处理方式
public class TimeTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyyMMdd");
Callable<LocalDate> task = new Callable<LocalDate>() {
@Override
public LocalDate call() throws Exception {
return LocalDate.parse("20161212", df);
}
};
ExecutorService service = Executors.newFixedThreadPool(10);
List<Future<LocalDate>> results = new ArrayList<>();
for (int i = 0; i < 10; i++) {
results.add(service.submit(task));
}
for (Future<LocalDate> result : results) {
System.out.println(result.get());
}
service.shutdown();
}
}
15.1 日期/时间
LocalDate(日期)、LocalTime(时间)、LocalDateTime(日期和时间)
public class TimeTest02 {
public static void main(String[] args) {
LocalDateTime ldt = LocalDateTime.now();
System.out.println(ldt);//2019-08-05T11:24:09.013
LocalDateTime ldt2 = LocalDateTime.of(2018, 8, 5, 11, 24, 15);
System.out.println(ldt2);//2018-08-05T11:24:15
// 对日期进行加操作
LocalDateTime ldt3 = ldt.plusYears(2);
System.out.println(ldt3);//2021-08-05T11:27:01.479
//对日期进行减操作
LocalDateTime ldt4 = ldt.minusMonths(2);
System.out.println(ldt4);//2019-06-05T11:28:38.154
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());
}
}
15.2 时间戳
Instant(时间戳):以Unix元年:1970年1月1日00:00:00到某个时间的毫秒值
Instant ins1 = Instant.now();//默认获取UTC时区
System.out.println(ins1);//2019-08-05T03:40:20.398Z
OffsetDateTime odt = ins1.atOffset(ZoneOffset.ofHours(8));
System.out.println(odt);//2019-08-05T11:40:20.398+08:00(北京时间)
System.out.println(ins1.toEpochMilli());//1564976586686
Instant ins2 = Instant.ofEpochSecond(60);
System.out.println(ins2);//1970-01-01T00:01:00Z
15.3 计算日期/时间间隔
Duration:计算俩个"时间"之间的间隔
//Duration 方式一
Instant now1 = Instant.now();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Instant now2 = Instant.now();
System.out.println(Duration.between(now1,now2).toMillis());
LocalTime local1 = LocalTime.now();
//Duration 方式二
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
LocalTime local2 = LocalTime.now();
System.out.println(Duration.between(local1,local2).toMillis());
Period:计算俩个"日期"之间的间隔
LocalDate localDate1 = LocalDate.of(2015, 1, 1);
LocalDate localDate2 = LocalDate.now();
Period period = Period.between(localDate1, localDate2);
System.out.println(period.getYears());
System.out.println(period.getMonths());
System.out.println(period.getDays());
15.4 时间矫正器
-
TemporalAdjuster:时间矫正器。有时我们可能需要获取例如:将日期调整到"下一个周日"等操作
-
TemporalAdjusters:该类通过静态方法提供了大量的常用TemporalAdjuster的实现
例如:
//获取下一个周日: LocalDate date = LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); System.out.println(date); //获取下一个工作日 LocalDateTime dateTime = LocalDateTime.now().with((dom) -> { LocalDateTime time = (LocalDateTime) dom; DayOfWeek dayOfWeek = time.getDayOfWeek(); if (dayOfWeek.equals(DayOfWeek.FRIDAY)) { return time.plusDays(3); } else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) { return time.plusDays(2); } else { return time.plusDays(1); } }); System.out.println(dateTime);
15.5 格式化日期/时间
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE;
LocalDateTime ldt = LocalDateTime.now();
String format = ldt.format(dtf);
System.out.println(format); //2019-08-06
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String str2 = ldt.format(pattern);
System.out.println(str2); //2019-08-06 16:38:23
LocalDateTime localDateTime = ldt.parse(str2,pattern);
System.out.println(localDateTime); //2019-08-06T16:38:23
15.6 时区日期/时间
ZonedDate、ZonedTime、ZonedDateTime
//获取所有的时区
ZoneId.getAvailableZoneIds().forEach(System.out::println);
//获取指定时区当前的时间值
LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Hongkong"));
System.out.println(ldt1);
//LocalDateTime转为ZonedDateTime
LocalDateTime ldt2 = LocalDateTime.now();
ZonedDateTime zdt1 = ldt2.atZone(ZoneId.of("Hongkong"));
System.out.println(zdt1);
15.6 LocalDateTime和java.lang.Date之前的转换
Date to LocalDateTime
Date todayDate = new Date();
LocalDateTime ldt = todayDate.toInstant()
.atZone( ZoneId.systemDefault() )
.toLocalDateTime();
System.out.println(ldt); //2020-11-19T16:29:12.773
LocalDateTime to Date
LocalDateTime localDateTime = LocalDateTime.now();
Date date = Date.from( localDateTime.atZone( ZoneId.systemDefault()).toInstant());
System.out.println(date);
//Thu May 16 16:32:37 CST 2020