欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

java--1.8时间API

程序员文章站 2024-02-29 20:24:34
...

概述

之前的时间API大部分过时过期的,都是线程不安全的,可变的;

新的API在java.time包下,整体都是不可变线程安全的,较之前的有规律许多;

java--1.8时间API

多线程安全问题

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);


     }