java--1.8时间API
程序员文章站
2024-02-29 20:24:34
...
概述
之前的时间API大部分过时过期的,都是线程不安全的,可变的;
新的API在java.time包下,整体都是不可变线程安全的,较之前的有规律许多;
多线程安全问题
jdk1.7
@Test
public void test01() throws Exception{
//指定时间日期格式
SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
Callable<Date> dateCallable = () -> {
return simpleDateFormat.parse("2016-11-02");
};
//线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
//执行10次
List<Future<Date>> futures=new ArrayList<>();
for (int i = 0; i < 10; i++) {
futures.add(executorService.submit(dateCallable));
}
futures.forEach(x->{
try {
System.out.println(x.get());
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
});
executorService.shutdown();
}
异常信息
java.util.concurrent.ExecutionException: java.lang.NumberFormatException: For input string: ""
at java.util.concurrent.FutureTask.report(FutureTask.java:122)
at java.util.concurrent.FutureTask.get(FutureTask.java:192)
at cn.bufanli.time.TimeDemo01.lambda$test01$1(TimeDemo01.java:37)
at java.util.ArrayList.forEach(ArrayList.java:1257)
at cn.bufanli.time.TimeDemo01.test01(TimeDemo01.java:35)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.lang.NumberFormatException: For input string: ""
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:601)
at java.lang.Long.parseLong(Long.java:631)
at java.text.DigitList.getLong(DigitList.java:195)
at java.text.DecimalFormat.parse(DecimalFormat.java:2051)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2162)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
at java.text.DateFormat.parse(DateFormat.java:364)
at cn.bufanli.time.TimeDemo01.lambda$test01$0(TimeDemo01.java:24)
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)
Wed Nov 02 00:00:00 CST 2016
Wed Nov 02 00:00:00 CST 2016
Mon Nov 02 00:00:00 CST 1970
Tue Nov 02 00:00:00 CST 1
jdk1.7--解决方法
加锁:
package cn.bufanli.time;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* @author BuShuangLi
* @date 2019/3/13
*/
public class DateFormaThreadLoca {
private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>(){
@Override
protected DateFormat initialValue() {
return new SimpleDateFormat("yyyy-MM-dd");
}
};
public static Date convet(String source) throws ParseException {
return df.get().parse(source);
}
}
测试
@Test
public void test02()throws Exception{
Callable<Date> callable = ()-> DateFormaThreadLoca.convet("2016-12-12");
ExecutorService executorService = Executors.newFixedThreadPool(10);
List<Future<Date>> futures = new ArrayList<>();
for (int i = 0; i < 10; i++) {
futures.add(executorService.submit(callable));
}
for (Future<Date> future : futures) {
System.out.println(future.get());
}
executorService.shutdown();
}
jdk1.8--解决方法
/**
* 1.8
*/
@Test
public void test03() {
DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//又返回值的线程 lambda表达式
Callable<LocalDate> callable = () -> LocalDate.parse("2011-12-22", df);
//创建线程池
ExecutorService executorService = Executors.newFixedThreadPool(10);
List< Future<LocalDate>> objects = new ArrayList<>();
for (int i = 0; i < 10; i++) {
objects.add(executorService.submit(callable));
}
//循环打印集合中的localDate对象
objects.forEach(x->{
try {
System.out.println(x.get());
} catch (Exception e) {
e.printStackTrace();
}
});
}
新时间日期的API
LocalDate(年月日)、LocalTime(时分秒)、LocalDateTime(年月日时分秒 ) 类的实例是不可变对象,分别表示ISO-8601日历系统的日期、时间、日期和时间.
它们提供了简单的日期或时间,并不包含当前的时间信息.也不包含与时区相关的信息
package cn.bufanli.time;
import org.junit.Test;
import java.time.*;
/**
* @author BuShuangLi
* @date 2019/3/13
*/
public class TestLocalDateTime {
/**
* 1.LocalDate--> (年月日) LocalTime-->(时分秒) LocalDateTime(年月日时分秒)
*/
@Test
public void test01(){
//获取当前系统时间 控制台: 2019-03-13T15:51:32.969
System.out.println(LocalDateTime.now());
//指定年月日分秒 控制台: 2012-12-22T12:33
LocalDateTime of = LocalDateTime.of(2012, 12, 22, 12, 33);
System.out.println(of);
//时间运算 +两年
LocalDateTime localDateTime = LocalDateTime.now().plusYears(2);
//输出 2021-03-13T15:56:58.571
System.out.println(localDateTime);
//-两个月
LocalDateTime localDateTime1 = LocalDateTime.now().minusMonths(2);
//输出 2019-01-13T15:58:58.231
System.out.println(localDateTime1);
//单独获取年月日..
System.out.println(localDateTime1.getYear());
//月
System.out.println(localDateTime1.getMonthValue());
//日
System.out.println(localDateTime1.getDayOfMonth());
//小时
System.out.println(localDateTime1.getHour());
}
/**
* 2.Instant : 时间戳(以Unix 元年 : 1970年1月1日 到某个时间的毫秒值)
*/
@Test
public void test02(){
// 默认获取的是 UTC 时区 输出: 2019-03-13T08:08:18.350Z
System.out.println(Instant.now());
//与UTC相差8小时时差
OffsetDateTime offsetDateTime = Instant.now().atOffset(ZoneOffset.ofHours(8));
//输出: 2019-03-13T16:10:41.398+08:00
System.out.println(offsetDateTime);
//转成毫秒值 1552464779665
System.out.println(Instant.now().toEpochMilli());
}
/**
* 3.
* Duration : 计算两个 时间 之间的间隔的
* Period : 计算两个日期之间的间隔
*/
@Test
public void test03() throws InterruptedException {
Instant now1 = Instant.now();
Thread.sleep(1000);
Instant now2 = Instant.now();
//获取毫秒 .toMillis() 其他的都是get..
System.out.println(Duration.between(now1, now2).toMillis());
LocalTime now11 = LocalTime.now();
Thread.sleep(1000);
LocalTime now22 = LocalTime.now();
System.out.println(Duration.between(now11, now22).toMillis());
}
}
日期的操纵
TemporalAdjuster:时间校正器.有时我们需要获取下个周日等操作
TemporalAdjusters: 该类通过静态方法提供了 大量的常用的TemporalAdjuster的实现
代码
/**
* TemporalAdjuster 时间教正器
*/
@Test
public void test04(){
LocalDateTime now = LocalDateTime.now();
System.out.println(now);
//输出
// 2019-03-13T16:28:02.746
// 2019-03-10T16:28:02.746
LocalDateTime localDateTime = now.withDayOfMonth(10);
System.out.println(localDateTime);
//获取下一个周日日期
LocalDateTime with = now.with(TemporalAdjusters.next(DayOfWeek.SUNDAY));
System.out.println(with);
//自定义 下一个工作日是什么时候
LocalDateTime with1 = now.with((l) -> {
LocalDateTime localDateTime1 = (LocalDateTime) l;
//获取周几
DayOfWeek dayOfWeek = localDateTime1.getDayOfWeek();
//判断
if (dayOfWeek.equals(DayOfWeek.FRIDAY)) {
return localDateTime1.plusDays(3);
} else if (dayOfWeek.equals(DayOfWeek.SATURDAY)) {
return localDateTime1.plusDays(2);
} else {
return localDateTime1.plusDays(1);
}
});
//输出下一个工作日的日期
System.out.println(with1);
}
DateTimeFormatter: 格式化时间/日期
/**
* DateTimeFormatter: 格式化时间/日期
*/
@Test
public void test05(){
DateTimeFormatter isoLocalDate = DateTimeFormatter.ISO_LOCAL_DATE;
LocalDateTime now = LocalDateTime.now();
String format = now.format(isoLocalDate);
System.out.println(format);
System.out.println("自定义");
//自定义
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
//日期解析成字符串
String format2 = now.format(dateTimeFormatter);
//字符串解析成日期LocalDateTime.parse(时间字符串,解析格式)
LocalDateTime parse = LocalDateTime.parse(format2, dateTimeFormatter);
System.out.println(parse);
}