我奶奶都能懂java8特性-日期时间

Posted 浦江之首

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了我奶奶都能懂java8特性-日期时间相关的知识,希望对你有一定的参考价值。

java每个版本的更新,都会给java使用者极大的方便。其中,java8中的日期时间较之前的版本的进步的不是一个数量级,java8的问世,之前的很多方法都已被弃用。借着这次针对java8基础的考试,本博客介绍一下之前版本的问题,以及java8版本的使用。示例的源码可以直接通过csdn下载也可以通过git导出:https://github.com/igdnss/java8_date-time.git

在这里插入图片描述

之前版本

老版本中提供的日期时间处理的两个重要的类为java.util.Date,java.util.Calendar。由于老版本的日期时间处理存在很多问题,因此很多方法都已经弃用 。例如,日期计算问题,存在线程不安全的问题。

示例
1,日期计算问题
某一商品生产日期为:2019年10月12日,距离当前有多少天。写起来真的很麻烦,我自己感觉都快疯了。

import java.time.LocalDate;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;

public class ProductDate {
	public static void main(String[] args) {
		//当前日期
		Date currentDate = new Date();
		//将日期转为long,方便计算(以格林维治为基础)
		long currentTime = currentDate.getTime();
		
		//定义商品生产日期
		Calendar productDate1 = Calendar.getInstance();
		//calendar中月份从0开始的,所以10月对应的应该是9,炸了。。。
		productDate1.set(2019, 9, 12);
		//将calendar 转换为date
		Date productDateFinal = productDate1.getTime();
		long productDateFinalTime = productDateFinal.getTime();
		//计算相隔的天数,算了算去,结果还不知道对不对。又炸一次
		long intervalDay1 = (currentTime-productDateFinalTime)/1000/60/60/24;
		System.out.println("老版本实现商品距离今日有:"+intervalDay1+"天");
		
		//java8 实现,一行代码
		long intervalDay2 = ChronoUnit.DAYS.between(LocalDate.of(2019, 10, 12), LocalDate.now());
		System.out.println("java8实现商品距离今日有:"+intervalDay2+"天");
	}
}

2,线程安全问题
创建20个线程,每个线程里以同样的格式创建一个日期。

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
public class DateThreadSafe {
	final static SimpleDateFormat TEST = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
	public static void main(String[] args) {
		// 20个线程,创建日期
		for (int i = 0; i < 20; i++) {
			Runnable runnable = () -> {
				Date date = null;
				try {
					date = TEST.parse("2020-11-11 10:10:10");
				} catch (ParseException e) {
					e.printStackTrace();
				}
				System.out.println(date);
			};

			new Thread(runnable).start();
		}

	}
}

结果中报NumberFormatException,至于原因大家自己去看一下源码,有一个clear函数。

java.lang.NumberFormatException: empty String
	at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1842)
	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:2162)
	at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1514)
	at java.text.DateFormat.parse(DateFormat.java:364)
	at date.DateThreadSafe.lambda$0(DateThreadSafe.java:17)
	at java.lang.Thread.run(Thread.java:748)

java8版本

这里介绍一下常用的一些类的常用用法,个人觉得这些基本能覆盖工作的需要,更深一步的学习,建议参考官方文档。但要强调一点的时,java8版本中的日期时间类生成的实例均为不可变的,它们是线程安全的,并且这些类不提供公共的构造方法,即不可以通过new来直接创建,而是通过工厂方法来创建。最常用的工厂方法有两个,now和of。另外还提供了三个修改日期的方法,plus,minus(内部也是使用plus实现的,不在举例),with。下文会对各个方法的使用作简单介绍。

Instant类

可以理解为某一精确的时间点,即时间戳,封装的时候为格林维治时间,常用于时间之间的转换。

Duration类

表示秒和纳秒的时间间隔,用于计算精确性较高的时间

Period类

表示一段时间的年、月、日

LocalDate类

表示一个不可变的日期对象,

LocalTime类

表示一个不可变的时间对象,包含纳秒部门

LocalDateTime类

表示一个不可变的日期时间对象,年-月-日 时-分-秒

ZoneDateTime类

表示一个具有时区的日期时间对象,存储了所示的日期和时间字段,精度为纳秒,时区为区域偏移量,用于处理模糊的本地日期时间。

使用

now方法的使用

根据当前时间或日期创建实例。接下来介绍的类的实例都可以通过now方法来创建。

示例1
使用Now创建日期,时间等

import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZonedDateTime;

public class NowExample1 {

	public static void main(String[] args) {
		Instant instant = Instant.now();
		System.out.println("instant:"+instant);
		LocalDate localDate = LocalDate.now();
		System.out.println("localDate:"+localDate);
		LocalTime localTime = LocalTime.now();
		System.out.println("localTime:"+localTime);
		LocalDateTime localDateTime = LocalDateTime.now();
		System.out.println("localDateTime:"+localDateTime);
		ZonedDateTime zonedDateTime = ZonedDateTime.now();
		System.out.println("zonedDateTime:"+zonedDateTime);	
	}
}
=====result=====
instant:2021-05-27T13:47:47.651Z //格林维治时间
localDate:2021-05-27 
localTime:21:47:47.701 //后三位表示纳秒
localDateTime:2021-05-27T21:47:47.701//后三位表示纳秒
zonedDateTime:2021-05-27T21:47:47.701+08:00[Asia/Shanghai] //东8区

示例2
使用Now创建年,月,日

import java.time.MonthDay;
import java.time.Year;
import java.time.YearMonth;

public class NowExample2 {
	public static void main(String[] args) {
		Year year = Year.now();
		System.out.println("year:"+year);
		YearMonth yearMonth = YearMonth.now();
		System.out.println("yearMonth:"+yearMonth);
		MonthDay monthDay = MonthDay.now();
		System.out.println("monthDay:"+monthDay);
	}
}
=====result=====
year:2021
yearMonth:2021-05
monthDay:--05-27

of方法的使用

now是根据当前时间或日期创建实例,如果需要创建指定的日期和时间那么就需要借助of方法来完成。接下来介绍的类的实例都可以通过now方法来创建。

示例
创建指定的LocalDate对象

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;

public class OfExample1 {

	public static void main(String[] args) {
		// 创建指定的LocalDate对象-- 2025-06-01,其中月份可以使用Month的枚举
		LocalDate localDate = LocalDate.of(2025, 06, 01);
		System.out.println("localDate:"+localDate);
		//创建指定的LocalTime对象--17:00
		LocalTime localTime = LocalTime.of(17, 0);//还有其它的形式,读都可以自己试试
		System.out.println(localTime);
		//第一种方法,创建指定的LocalDateTime对象--2025-06-01 17:00
		LocalDateTime localDateTime1 = LocalDateTime.of(2025, 06, 01, 17, 0);
		System.out.println("localDateTime1:"+localDateTime1);
		//第二种方法,创建指定的LocalDateTime对象--2025-06-01 17:00
		LocalDateTime localDateTime2 = LocalDateTime.of(localDate, localTime);
		System.out.println("localDateTime2:"+localDateTime2);
		//为LocalDateTime添加时区
		ZonedDateTime atZone = localDateTime2.atZone(ZoneId.of("Asia/Shanghai"));//zoneId可以通过ZoneId.getAvailableZoneIds()获取
		System.out.println("atZone: "+atZone);		
	}
}

plus方法的使用

plus可以实现对LocalDate和LocalTime进行增加的功能。
LoalDate

 //增加天数
 LocalDate plusDays(long days) 
 //增加周数
 LocalDate plusWeeks(long weeks)
 //增加月数
 LocalDate plusMonths(long months)
 //增加年数
 LocalDate plusYears(long years)

示例
在当前的日期基础上做各种增加操作

import java.time.LocalDate;
import java.time.Month;

public class PlusDate {

	public static void main(String[] args) {
		LocalDate localDate = LocalDate.of(2025, Month.JUNE, 1);
		System.out.println("localDate : "+localDate);
		 //增加5天
		 LocalDate localDatePlus5Days = localDate.plusDays(5); 
		 System.out.println("localDatePlus5Days : "+localDatePlus5Days);
		 //增加1周
		 LocalDate localDatePlus1Week = localDate.plusWeeks(1);
		 System.out.println("localDatePlus1Week : "+localDatePlus1Week );
		 //增加1月
		 LocalDate localDatePlus1Month = localDate.plusMonths(1);
		 System.out.println("localDatePlus1Month : "+localDatePlus1Month );
		 //增加1年
		 LocalDate localDatePlus1Year = localDate.plusYears(1);
		 System.out.println("localDatePlus1Year : "+localDatePlus1Year);
		//增加1年1个月
		 LocalDate localDatePlus1YearAnd1Month = localDate.plusYears(1).plusMonths(1);
		 System.out.println("localDatePlus1Year : "+localDatePlus1YearAnd1Month);
	}

}

LocalTime

//增加纳秒
LocalTime plusNanos(long nanos)
//增加秒
LocalTime plusSeconds(long seconds)
//增加分钟
LocalTime plusMinutes(long minutes)
//增加小时
LocalTime plusHours(long hours)

示例
在当前的时间基础上做各种增加操作

import java.time.LocalTime;

public class PlusTime {

	public static void main(String[] args) {
		LocalTime localTime = LocalTime.of(11, 49, 11, 500);
		System.out.println("localTime : "+localTime);
		//增加100纳秒
		LocalTime plus100Nanos = localTime.plusNanos(100);
		System.out.println("plus100Nanos : "+plus100Nanos);
		//增加9秒
		LocalTime plus9Seconds = localTime.plusSeconds(9);
		System.out.println("plus9Seconds : "+plus9Seconds);
		//增加1分钟
		LocalTime plusMinutes = localTime.plusMinutes(1);
		System.out.println("plusMinutes : "+plusMinutes);
		//增加1小时
		LocalTime plus1Hours = localTime.plusHours(1);
		System.out.println("plus1Hours : "+plus1Hours);
		//增加1小时1分钟
		LocalTime plus1Hour1Minute = localTime.plusHours(1).plusMinutes(1);
		System.out.println("plus1Hour1Minute : "+plus1Hour1Minute);

	}

}

Period
示例
在当前时间的基础上加1年两个月零3天

import java.time.LocalDate;
import java.time.Period;

public class Plus1 {
	public static void main(String[] args) {
		//在当前时间的基础上加1年两个月零3天
		LocalDate now = LocalDate.now();
		System.out.println("now:"+now);
		//方法1
		LocalDate plusPeriod1 = now.plusYears(1).plusMonths(2).plusDays(3);
		System.out.println("plusPeriod1: " +plusPeriod1);
		//方法2
		Period period = Period.of(1, 2, 3);
		LocalDate plusPeriod2 = now.plus(period);
		System.out.println("plusPeriod2: " +plusPeriod2);
	}
}

ChronoUnit
ChronoUnit提供了一系列方便日期运算的枚举,例如10年,100年,1个世纪等。
示例
在原有的日期基础上增加20年

import java.time.LocalDate;
import java.time.Month;
import java.time.temporal.ChronoUnit;

public class ChronoUnitPlus {

	public static void main(String[] args) {
		LocalDate localDate = LocalDate.of(2024, Month.MAY,3);
		System.out.println(&#

以上是关于我奶奶都能懂java8特性-日期时间的主要内容,如果未能解决你的问题,请参考以下文章

我奶奶都能懂java枚举类型

我奶奶都能懂java泛型

我奶奶都能懂docker基本操作

我奶奶都能懂java异常

我奶奶都能懂java枚举类型

我奶奶都能懂java子类构造方法