• Java8新特性——新一套时间API的使用


    JDK 1.0中包含了一个java.util.Date类,但是它的大多数方法已经在JDK 1.1引入Calendar类之后被弃用了。而Calendar并不比Date好多少。它们面临的问题是:
    可变性:像日期和时间这样的类应该是不可变的。
    偏移性:Date中的年份是从1900开始的,而月份都从0开始。
    格式化:格式化只对Date有用,Calendar则不行。
    此外,它们也不是线程安全的;不能处理闰秒等。
    关于线程安全问题,下面举个例子

    package com.xnn.time;
    
    import java.text.SimpleDateFormat;
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 类(接口)描述:
     * @author xnn
     * 2018年10月24日下午10:59:06
     */
    public class TestSimpleDateFormat {
    public static void main(String[] args) throws Exception {
    	//定义日期格式
    	SimpleDateFormat format = new SimpleDateFormat("yyyyMMdd");
    	Callable<Date> callable = new Callable<Date>() {
    		
    		@Override
    		public Date call() throws Exception {
    			return  format.parse("20181024");
    		}
    	};
    	//创建一个有10个线程的线程池
    	ExecutorService pool = Executors.newFixedThreadPool(10);
    	List<Future<Date>> futures = new ArrayList<>();
    	for (int i = 0; i < 10; i++) {
    		//把每个线程执行的结果放在集合中去
    		futures.add(pool.submit(callable));
    	}
    	for (Future<Date> future : futures) {
    		System.out.println(future.get());
    	}
    }
    }
    
    
    

    运行结果

    Exception in thread "main" java.util.concurrent.ExecutionException: java.lang.NumberFormatException: multiple points
    	at java.util.concurrent.FutureTask.report(FutureTask.java:122)
    	at java.util.concurrent.FutureTask.get(FutureTask.java:192)
    	at com.xnn.time.TestSimpleDateFormat.main(TestSimpleDateFormat.java:37)
    Caused by: java.lang.NumberFormatException: multiple points
    	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1890)
    	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:2056)
    	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 com.xnn.time.TestSimpleDateFormat$1.call(TestSimpleDateFormat.java:28)
    	at com.xnn.time.TestSimpleDateFormat$1.call(TestSimpleDateFormat.java:1)
    	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
    	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    	at java.lang.Thread.run(Thread.java:745)
    
    

    报了个并发异常的错,
    在Java8之前,我们都是通过加锁来处理诸如此类的问题。

    /**
     * 
     */
    package com.xnn.time;
    
    import java.text.DateFormat;
    import java.text.SimpleDateFormat;
    import java.util.Date;
    
    /**
     * 类(接口)描述:线程池锁
     * @author xnn
     * 2018年10月25日上午9:39:07
     */
    public class DateFormatThreadLocal {
    private static final ThreadLocal<DateFormat> df = new ThreadLocal<DateFormat>() {
    	//重写ThreadLocal类的initialValue()方法没返回一个
    	protected DateFormat initialValue() {
    		return new SimpleDateFormat("yyyyMMdd");
    	}
    };
    //解析时间
    public static Date convert (String source) throws Exception {
    	return df.get().parse(source);
    }
    }
    
    
    package com.xnn.time;
    
    import java.util.ArrayList;
    import java.util.Date;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 类(接口)描述:
     * @author xnn
     * 2018年10月24日下午10:59:06
     */
    public class TestSimpleDateFormat {
    public static void main(String[] args) throws Exception {
    	Callable<Date> callable = new Callable<Date>() {
    		
    		@Override
    		public Date call() throws Exception {
    			return  DateFormatThreadLocal.convert("20181024");
    		}
    	};
    	//创建一个有10个线程的线程池
    	ExecutorService pool = Executors.newFixedThreadPool(10);
    	List<Future<Date>> futures = new ArrayList<>();
    	for (int i = 0; i < 10; i++) {
    		//把每个线程执行的结果放在集合中去
    		futures.add(pool.submit(callable));
    	}
    	for (Future<Date> future : futures) {
    		System.out.println(future.get());
    	}
    	pool.shutdown();
    }
    }
    
    

    运行结果

    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    Wed Oct 24 00:00:00 CST 2018
    

    第三次引入的API是成功的,并且java 8中引入的java.time API 已经纠正了过去的缺陷,将来很长一段时间内它都会为我们服务。
    Java 8 吸收了 Joda-Time 的精华,以一个新的开始为 Java 创建优秀的 API。新的 java.time 中包含了所有关于本地日期(LocalDate)、本地时间(LocalTime)、本地日期时间(LocalDateTime)、时区(ZonedDateTime)和持续时间(Duration)的类。历史悠久的 Date 类新增了 toInstant() 方法,用于把 Date 转换成新的表示形式。这些新增的本地化时间日期 API 大大简化了日期时间和本地化的管理.
    java.time – 包含值对象的基础包
    java.time.chrono – 提供对不同的日历系统的访问
    java.time.format – 格式化和解析时间和日期
    java.time.temporal – 包括底层框架和扩展特性
    java.time.zone – 包含时区支持的类

    说明:大多数开发者只会用到基础包和format包,也可能会用到temporal包。因此,尽管有68个新的公开类型,大多数开发者,大概将只会用到其中的三分之一。

    现在有了新的时间日期API可以完美解决线程安全问题

    
    package com.xnn.time;
    
    import java.time.LocalDate;
    import java.time.format.DateTimeFormatter;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.Callable;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    
    /**
     * 类(接口)描述:
     * @author xnn
     * 2018年10月24日下午10:59:06
     */
    public class TestSimpleDateFormat {
    public static void main(String[] args) throws Exception {
    	//用LocalDate类
    	Callable<LocalDate> callable = new Callable<LocalDate>() {
    		@Override
    		public LocalDate call() throws Exception {
    			//定义格式用DateTimeFormater类
    			DateTimeFormatter formatter =DateTimeFormatter.ofPattern("yyyyMMdd")  ;
    
    			return LocalDate.parse("20181025",formatter);
    		}
    	};
    	//创建一个有10个线程的线程池
    	ExecutorService pool = Executors.newFixedThreadPool(10);
    	List<Future<LocalDate>> futures = new ArrayList<>();
    	for (int i = 0; i < 10; i++) {
    		//把每个线程执行的结果放在集合中去
    		futures.add(pool.submit(callable));
    	}
    	for (Future<LocalDate> future : futures) {
    		System.out.println(future.get());
    	}
    	pool.shutdown();
    }
    }
    
    

    本地时间与时间戳LocalDate LocalTime LocalDateTime

    LocalDate、LocalTime、LocalDateTime 类是其中较重要的几个类,它们的实例是不可变的对象,分别表示使用 ISO-8601日历系统的日期、时间、日期和时间。它们提供了简单的本地日期或时间,并不包含当前的时间信息,也不包含与时区相关的信息

    
    package com.xnn.time;
    
    import java.time.DayOfWeek;
    import java.time.Duration;
    import java.time.Instant;
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.OffsetDateTime;
    import java.time.Period;
    import java.time.ZoneId;
    import java.time.ZoneOffset;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;
    import java.time.temporal.TemporalAdjuster;
    import java.time.temporal.TemporalAdjusters;
    
    import org.junit.Test;
    
    /**
     * 类(接口)描述:
     * @author xnn
     * 2018年10月25日上午10:39:10
     */
    public class TestLocalDAteTime {
    	//1、LocalDate  LocalTime  LocalDateTime
    @Test
    public void test() {
    	//now()方法 获取当前系统时间
    	LocalDateTime dateTime = LocalDateTime.now();
    	System.out.println("当前时间:"+dateTime);
    	LocalDateTime dateTime2 = LocalDateTime.of(2018, 10, 10, 10, 10, 10);
    	System.out.println("自定义的时间:"+dateTime2);
    	//对时间的运算
    	LocalDateTime plusYears = dateTime.plusYears(1);
    	System.out.println("对当前时间加一年:"+plusYears);
    	LocalDateTime minusYears = dateTime.minusYears(2);
    	System.out.println("对当前时间减去两年:"+minusYears);
    	//get系列
    	System.out.println("得到当前时间的年:"+dateTime.getYear());
    	System.out.println("得到当前时间的年月;"+dateTime.getMonth().getValue());
    }
    }
    

    运行结果:

    当前时间:2018-10-25T12:02:21.250
    自定义的时间:2018-10-10T10:10:10
    对当前时间加一年:2019-10-25T12:02:21.250
    对当前时间减去两年:2016-10-25T12:02:21.250
    得到当前时间的年:2018
    得到当前时间的年月;10
    
    

    Instant:时间戳(以uninx元年:1970年1月1日00:00:00到某个时间的毫秒值)

    //Instant:时间戳(以uninx元年:1970年1月1日00:00:00到某个时间的毫秒值)
    @Test
    public void test1() {
    	Instant instant = Instant.now();//默认获取UTC时区,我们是东八区,相差八小时
    	System.out.println("当前UTC时区的时间:"+instant);
    	//带偏移量的
    	OffsetDateTime offset = instant.atOffset(ZoneOffset.ofHours(8));
    	System.out.println("偏移了8小时的时区的时间"+offset);
    	//转化成毫秒值
    	System.out.println("毫秒值:"+instant.toEpochMilli());
    	//从1970年1月1日00:00:00加了1000毫秒
    	Instant instant2 =Instant.ofEpochMilli(1000);
    	System.out.println("从1970年一月一日加上一秒:"+instant2);
    }
    

    结果:

    当前UTC时区的时间:2018-10-25T04:07:31.595Z
    偏移了8小时的时区的时间2018-10-25T12:07:31.595+08:00
    毫秒值:1540440451595
    从1970年一月一日加上一秒:1970-01-01T00:00:01Z
    

    Duration Period

    //Duration:计算两个时间的间隔
    //Period:计算两个日期间的间隔
    @Test
    public void test2() throws Exception {
    	Instant instant = Instant.now();
    	Thread.sleep(1000);
    	Instant instant1 = Instant.now();
    	Duration duration = Duration.between(instant, instant1);
    	System.out.println("间隔是"+duration.toMillis()+"毫秒");
    	System.out.println("=============");
    	
    	LocalDateTime time = LocalDateTime.now();
    	Thread.sleep(1000);
    	LocalDateTime time1 = LocalDateTime.now();
    	Duration duration1 = Duration.between(time, time1);
    	System.out.println(duration1.toMillis()+"毫秒");
    	//两个日期的间隔
    	LocalDate date = LocalDate.of(2018, 1, 1);
    	LocalDate date1 = LocalDate.now();
    	Period period = Period.between(date, date1);
    	System.out.println("两个日期的间隔是"+period.getYears()+"年"+period.getMonths()+"月"+period.getDays()+"天");
    
    }
    

    运行结果

    间隔是1000毫秒
    =============
    1000毫秒
    两个日期的间隔是0年9月24天
    

    TemporalAdjuster:时间校正器

    //TemporalAdjuster:时间校正器
    @Test
    public void test3() throws Exception {
    	LocalDateTime dateTime =LocalDateTime.now();
    	System.out.println("当前时间是:"+dateTime);
        //把月中的天指定为自己设定的数值
    	LocalDateTime dayOfMonth = dateTime.withDayOfMonth(10);
    	System.out.println("自己设定的值:"+dayOfMonth);
    	//下个周日
    	TemporalAdjuster adjuster = TemporalAdjusters.next(DayOfWeek.SUNDAY);
    	LocalDateTime with = dateTime.with(adjuster );
    	System.out.println("下个周日是"+with);
    	//也可以自定义(比如下个周日)
    	LocalDateTime with2 = dateTime.with((l)->{
    		LocalDateTime dateTime1 =(LocalDateTime)l;
    		if(dateTime1.equals(DayOfWeek.FRIDAY)) {
    			return dateTime1.plusDays(3);
    		}else if(dateTime1.equals(DayOfWeek.SATURDAY)) {
    			return dateTime1.plusDays(2);
    		}
    		else {
    			return dateTime1.plusDays(1);
    		}
    	});
    	System.out.println("下个工作日是:"+with2);
    }
    

    运行结果

    当前时间是:2018-10-25T12:11:46.891
    自己设定的值:2018-10-10T12:11:46.891
    下个周日是2018-10-28T12:11:46.891
    下个工作日是:2018-10-26T12:11:46.891
    

    DateTimeFormater:格式化日期时间

    //DateTimeFormater:格式化日期时间
    @Test
    public void test4() throws Exception {
    	DateTimeFormatter isoDateTime = DateTimeFormatter.ISO_DATE;
    	LocalDateTime dateTime = LocalDateTime.now();
    	String format = dateTime.format(isoDateTime);
    	System.out.println("ISO_DATE格式:"+format);
    	System.out.println("+++++++++++++++++");
    	//把时间日期指定为特定格式的字符串形式
    	DateTimeFormatter isoDateTime1 = DateTimeFormatter.ofPattern("yyyy年MM月dd日 HH:mm:ss");
    	String format2 = dateTime.format(isoDateTime1);
    	System.out.println(""ISO_DATE格式:"+格式"+format2);
    	
    	System.out.println("+++++++++++++++++");
    	
    	//解析日期时间(按照特定的格式)
    	LocalDateTime parse = LocalDateTime.parse(format2, isoDateTime1);
    	System.out.println("解析后得到时间:"+parse);
    
    }
    

    ZonedDate ZonedDate ZoneDateTime 带时区的操作

    //ZonedDate ZonedDate  ZoneDateTime 带时区的操作
    @Test
    public void test5() throws Exception {
    	
    	LocalDateTime now = LocalDateTime.now();
    	System.out.println(now);
    	
    	ZonedDateTime zone = now.atZone(ZoneId.of("Asia/Shanghai"));
    	System.out.println("上海时区"+zone);
    }
    

    运行结果

    2018-10-25T12:20:58.861
    上海时区2018-10-25T12:20:58.861+08:00[Asia/Shanghai]
    
  • 相关阅读:
    8皇后问题
    求1到n,n个整数的全排列
    求最小周期串
    如何用java完成一个中文词频统计程序
    蛇形矩阵
    第一个算法程序
    java 继承练习题8
    java 继承练习题7
    java 继承练习题6
    java 继承练习题5
  • 原文地址:https://www.cnblogs.com/nnxud/p/9847032.html
Copyright © 2020-2023  润新知