ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

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

2021-05-30 12:58:03  阅读:173  来源: 互联网

标签:java System 日期 奶奶 println import LocalDate java8 out


java每个版本的更新,都会给java使用者极大的方便。其中,java8中的日期时间较之前的版本的进步的不是一个数量级,java8的问世,之前的很多方法都已被弃用。借着这次针对java8基础的考试,本博客介绍一下之前版本的问题,以及java8版本的使用。

之前版本

老版本中提供的日期时间处理的两个重要的类为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("localDate : "+localDate);
		//在原有的日期基础上增加20年
		LocalDate chronoUnitPlus = localDate.plus(2, ChronoUnit.DECADES);
		System.out.println("chronoUnitPlus : "+chronoUnitPlus);
	}
}

with方法的使用

如果不需要对日期进行加减操作,而是直接修改日期,这时with方法就派有用场了。with方法在工作中我使用的不多,印象中只使用过一次。with方法可以直接传入一个整型,也可以传入一个枚举值,还可以传入一个时间调节器对象(TemporalAdjuster)。在修改的时候可以充分java8自带的枚举类型,真的很好用。

示例
将日期改为当月1号

import java.time.LocalDate;
import java.time.temporal.ChronoField;
import java.time.temporal.TemporalAdjusters;

/**
 *将日期改为当月的1号
 */
public class With {

	public static void main(String[] args) {
		LocalDate now = LocalDate.now();
		System.out.println("now:"+now);
		//方法1
		LocalDate withDayOfMonth1 = now.withDayOfMonth(1);
		System.out.println("withDayOfMonth:"+withDayOfMonth1);
		//方法2
		LocalDate withDayOfMonth2 = now.with(ChronoField.DAY_OF_MONTH, 1);
		System.out.println("withDayOfMonth2:"+withDayOfMonth2);
		//方法3
		LocalDate withDayOfMonth3 = now.with(TemporalAdjusters.firstDayOfMonth());
		System.out.println("withDayOfMonth3:"+withDayOfMonth3);
	}

}

旧版本日期转换为java8版本

这个用到的不多,除非在阳项目重构的过程可能会使用到,做一个简短的总结。老版本的日期时间放在java.util包中,java8中放在java.time包中,两者之间的互转一般借助于Instant类,java.sql.Date以及java.sql.Timestamp类。

使用Instant类转换两者的日期

import java.time.Instant;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Date;

public class DateConverter1 {

	public static void main(String[] args) {
		Date date = new Date();
		System.out.println("老版本date:"+date);
		//toInstant()是java8向date中添加一个方法,专门用来做日期转换的
		Instant instant = date.toInstant();
		//这里需要添加时区信息,老版本没有时区信息
		ZonedDateTime atZone = instant.atZone(ZoneId.systemDefault());
		LocalDate localDate = atZone.toLocalDate();
		System.out.println("java版本date:"+localDate);
	}

}

使用sql.Date类转换两者的日期

import java.sql.Date;
import java.sql.Timestamp;
import java.time.LocalDate;
import java.time.LocalDateTime;

public class DateConverter2 {

	public static void main(String[] args) {
		//sql.Date直接转换为LocalDate
		Date sqlDate1 = new Date(System.currentTimeMillis());
		System.out.println("sql date : "+sqlDate1);
		LocalDate localDate1 = sqlDate1.toLocalDate();
		System.out.println("localDate1:"+localDate1);
		//sql.Timestamp 转换为LocalDateTime
		Timestamp timeStamp = new Timestamp(System.currentTimeMillis());
		System.out.println("sql timestamp:"+timeStamp);
		LocalDateTime localDateTime = timeStamp.toLocalDateTime();
		System.out.println("localDatetime:"+localDateTime);
		
		//将util.Date转换为sql.Date,再转换为LocalDate
		java.util.Date date2 = new java.util.Date();
		System.out.println("date2:"+date2);
		Date sqlDate2 = new Date(date2.getTime());
		System.out.println("sqlDate2:"+sqlDate2);
		LocalDate localDate2 = sqlDate2.toLocalDate();
		System.out.println("localDate2:"+localDate2);
		
	}

}

Calendar类转换为ZoneDateTime

import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.TimeZone;

public class CalendarConverter1 {

	public static void main(String[] args) {
		Calendar calendar = Calendar.getInstance();
		System.out.println("calendar:"+calendar);
		TimeZone timeZone = calendar.getTimeZone();
		ZoneId zoneId = timeZone.toZoneId();
		ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(calendar.toInstant(), zoneId);
		System.out.println("zonedDateTime:"+zonedDateTime);
	}

}

Calendar类转换为LocalDateTime

import java.time.LocalDateTime;
import java.util.Calendar;

public class CalendarConverter2 {
	public static void main(String[] args) {
		Calendar calendar = Calendar.getInstance();
		int year = calendar.get(Calendar.YEAR);
		int month = calendar.get(Calendar.MONTH);
		int day = calendar.get(Calendar.DAY_OF_MONTH);
		int hour = calendar.get(Calendar.HOUR);
		int min = calendar.get(Calendar.MINUTE);
		int seconds = calendar.get(Calendar.SECOND);
		//Calendar中month从0开始,所以需要加1
		LocalDateTime localDateTime = LocalDateTime.of(year,month+1, day, hour, min,seconds);
		System.out.println("localDateTime:"+localDateTime);
	}

}

java8日期格式与Parse

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.FormatStyle;

public class FormatAndParse {

	public static void main(String[] args) {
		LocalDateTime now = LocalDateTime.now();
		System.out.println("now:"+now);
		//DateTimeFormatterr提供了很多格式,这里使用最常用的
		String format1 = now.format(DateTimeFormatter.ISO_DATE_TIME);
		System.out.println("format1:"+format1);
		String format2 = now.format(DateTimeFormatter.ISO_DATE);
		System.out.println("format2:"+format2);
		//使用FormatStyle格式化
		DateTimeFormatter formatStyle1 = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
		System.out.println("formatStyle1:"+now.format(formatStyle1));
		DateTimeFormatter formatStyle2 = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
		System.out.println("formatStyle2:"+now.format(formatStyle2));
		//使用DateTimeFormatter.ofPattern()自定义格式,格式化的写法与SimpleDateFormat一样
		DateTimeFormatter formatStyle3 = DateTimeFormatter.ofPattern("yyyy:MM:dd HH:mm:ss");
		System.out.println("formatStyle3:"+now.format(formatStyle3));
		//将一个字符串转换为LocalDateTime
		LocalDateTime parseTime = LocalDateTime.parse(format1);
		System.out.println("parsetime:"+parseTime);
		
	}

}

到这,可以告一段落了,基本上java8的日期时间类的使用方法都覆盖了,希望能帮助大家,文章中的不足,感谢各位大神的指正。

标签:java,System,日期,奶奶,println,import,LocalDate,java8,out
来源: https://blog.csdn.net/hongyinanhai00/article/details/115936153

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有