Java8 日期和时间

1.介绍

如果曾经使用过java8之前处理日期和时间的api,就知道java.util.Date以及java1.1中引入的java.util.Calendar类有些许难用。比如Date的年份起始是1900年,月份的起始是从0开始的,一周开始是周日,周日用1表示。如想要表示2020年1月25日,我们的代码可能写成这样:

Date date = new Date(120,0,25);
//打印结果
Sat Jan 25 00:00:00 CST 2020

这个打印结果可读性极差,你可能想到将日期和时间解析并格式化,那么需要用到一个抽象类DateFormat,常见到的是它的子类SimpleDateFormatSimpleDateFormat是线程不安全的,如果两个线程同时进行操作,结果可能不符合预期。此外Date和Calendar类都是可变的,也就说我们想要在date加上7天返回日期副本,但此操作会将原先的日期也进行了修改。
java8借鉴了Joda-Time框架,使我们处理日期和时间更加简单。通过下面一张表看下java8中比较重要的几个类。

类名 解释
LocalDate,LocalTime,LocalDateTime 本地日期和时间
Duration,Period 日期-时间间隔
DateTimeFormatter 格式化日期和时间
Instant 时刻(时间戳)
ZoneId,ZoneOffSet 时区有关变量
ZonedDateTime 带有时区的日期和时间

可以看出java8中对日期、时间、带有时区的日期时间、时刻等有了严格的区分

2.LocalDate、LocalTime、LocalDateTime、Instant、Duration以及Period
2.1 LocalDate、LocalTime和LocalDateTime

LocalDate提供了简单的日期,不包含时间信息,可以操作年份,月份,日,以及星期几这些日期信息。LocalTime提供的是一天中的时间,比如13:14:20,可以操作时,分,秒这些时间信息。LocalDateTimeLocalDateLocalTime的合体,它同时表示了日期和时间,但是不带有时区信息。翻看三个类的api,可以发现它们的大部分方法具有相似性。

————创建对象方式
比较常见的方式有以下几种:
1.通过of()方法来创建。
    LocalDate,LocalTime,LocalDateTime都分别有几种类型的of()重载方法,比如可以通过LocalDate.of()方法指定年份,月份,日来返回一个LocalDate,其中月份可以通过数字或者Month枚举类型来指定。而LocalDateTime由于是日期和时间复合,因此可以通过LocalDateTime.of()方法指定年份,月份,日,小时,分钟,秒,纳秒来返回LocalDateTime,还可以传入LocalDate和LocalTime来返回一个LocalDateTime。

//指定年份,月份,日
LocalDate localDate = LocalDate.of(2020, 5, 20);
//指定小时,分钟,秒
LocalTime localTime = LocalTime.of(13, 14, 20);
//指定年份,月份,日,小时,分钟,秒
LocalDateTime ldf = LocalDateTime.of(2020, 5, 20, 13, 14, 20);
//参数传入LocalDate,LocalTime
LocalDateTime ldf2 = LocalDateTime.of(localDate ,localTime );

2.通过now()重载方法创建当前日期-时间。
now()方法返回当前默认时区日期和时间信息,它还有另外两种重载方法,now(ZoneId zone)now(Clock clock)。实际上now()方法底层会调用now(Clock clock)方法,参数传入系统默认Clock

//获取当前日期
LocalDate ld = LocalDate.now();
//获取当前时间
LocalTime lt = LocalTime.now();
//获取当前日期-时间
LocalDateTime ldt = LocalDateTime.now();
//通过ZoneId来指定时区
LocalDateTime ldt1 = LocalDateTime.now(ZoneId.of("Asia/Shanghai"));
//通过指定一个clock实例
LocalDateTime ldt2 = LocalDateTime.now(Clock.systemDefaultZone());

3.通过parse()重载方法解析字符串
LocalDate,LocalTime,LocalDateTime默认会按照ISO 8601日历系统的日期和时间格式解析字符串和打印。日期和时间分隔符是T,默认带有毫秒的日期时间标准格式为yyyy-MM-dd'T'HH:mm:ss.SSS。另外parse()方法也提供了按自定义格式解析的方法parse(CharSequence text, DateTimeFormatter formatter)

//按照ISO-8601日期格式解析,如2020-05-20
LocalDate parseDate = LocalDate.parse("2020-05-20");
//按照ISO-8601时间格式解析,如13:14,13:14:20
LocalTime parseTime = LocalTime.parse("13:14:20");
//按照ISO-8601日期时间格式解析,如2020-05-20T13:14:20
LocalDateTime parseDateTime = LocalDateTime.parse("2020-05-20T13:14:20");
//指定日期时间解析格式
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = LocalDateTime.parse("2020-10-20 13:14:15", dateTimeFormatter);

————获取日期和时间字段值
1、getXXXX()方法读取字段值
以LocalDateTime为例,LocalDateTime实例提供了getXXXX()方法读取日期-时间字段值,如年份,月份,日,周几等。LocalDate和LocalTime也是类似的。LocalDate有相应获取日期字段的getXXXX()方法(如年,月,日等),而LocalTime则提供了获取时间字段getXXXX()方法(如时,分,秒等)。

LocalDateTime dateTime = of(2020, 2, 21, 13, 14, 20);
System.out.println(dateTime.getYear());//年份
System.out.println(dateTime.getMonth());//月份
System.out.println(dateTime.getDayOfMonth());//月中第几天
System.out.println(dateTime.getDayOfWeek());//星期几
System.out.println(dateTime.getDayOfYear());//年中第几天
System.out.println(dateTime.getHour());//小时
System.out.println(dateTime.getMinute());//分钟
System.out.println(dateTime.getSecond());//秒

2、通用方法get(TemporalField field)读取字段值
上面通过getXXXX()方法获取字段值,可以通过通用方法get(TemporalField field)来获取同样的字段值,其中TemporalField是一个接口,它定义了如何访问temporal对象某个字段的值。 ChronoField 枚举实现了这一接口,可以使用 get() 方法得到枚举元素的值。

LocalDateTime localDateTime = of(2020, 2, 21, 13, 14, 20);
System.out.println(dateTime.get(ChronoField.YEAR));
System.out.println(dateTime.get(ChronoField.MONTH_OF_YEAR));
System.out.println(dateTime.get(ChronoField.DAY_OF_MONTH));
LocalTime localTime = LocalTime.of(13,14,20);
System.out.println(localTime.get(ChronoField.HOUR_OF_DAY));
System.out.println(localTime.get(ChronoField.MINUTE_OF_HOUR));
System.out.println(localTime.get(ChronoField.SECOND_OF_MINUTE));

这里需要注意一点的是LocalDate因为表示的是日期,包含了年,月,日等字段,因此应该向它的get()方法传入比如ChronoField.HOUR_OF_DAY日期字段枚举值。同样LocalTime表示的是时间,可以向它的get()传入小时,分钟,秒等枚举值,如果传入ChronoField.YEAR这样的日期枚举类型,将会抛出UnsupportedTemporalTypeException异常。

————操作日期和时间
1、日期和时间字段修改操作
通过withXXXX()方法来修改指定字段的值,withXXXX()方法会创建一个原先对象副本,并按要求修改对应字段值,方法不会改变原来的日期-时间对象。

LocalDateTime dateTime = of(2020, 2, 21, 13, 14, 20);
LocalDateTime changeYear = dateTime.withYear(2008);//2008-02-21T13:14:20
LocalDateTime changeDayOfMonth = dateTime.withDayOfMonth(29);//2020-02-29T13:14:20
LocalTime localTime = LocalTime.of(13,14,20);
LocalTime changeMinute = localTime.withMinute(
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值