JAVA8 日期时间API整理

Posted 李某乐

tags:

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

JAVA中的日期时间api

JDK1.0的时候,Java引入了java.util.Date来处理日期和时间;在JDK1.1的时候又引入了功能更强大的java.util.Calendar,但是Calendar的API还是不尽如人意,,存在实例易变、没有处理闰秒等等的问题。所以在JDK1.8的时候,Java引入了java.time,这才真正修改了过去的缺陷,且更为好用。本篇就大致整理一下JDK1.8的日期和时间API。

JAVA8 日期时间

在java8中,java.time包下主要包含下面几个主要的类:

Instant:时间戳,相当于java.util的Date
LocalDate:只包含日期,比如:2021-03-21
LocalTime:只包含时间,比如:12:06:47
LocalDateTime:包含日期和时间,比如:2021-03-21 12:06:50
Duration:计算两个“时间”的间隔
Period:用于计算两个“日期”的间隔
ZoneOffset:时区偏移量,比如:+12:00
ZonedDateTime:可以得到特定时区的日期/时间
Clock:时钟,比如获取目前美国纽约的时间

时间格式化使用DateTimeFormatter代替了原来java.text中的SimpleDateFormat

DateTimeFormatter:时间格式化

java8也提供了一系列的具有前缀含义的方法,例如:plus增加、minux减少、format格式化、、、

of:静态工厂方法(用类名去调用)。
parse:静态工厂方法,关注于解析(用类名去调用)。
now: 静态工厂方法,用当前时间创建实例(用类名去调用)
get:获取某些东西的值。
is:检查某些东西的是否是true。
with:返回一个部分状态改变了的时间日期对象拷贝(单独一个with方法,参数为TemporalAdjusters类型)。
plus:返回一个时间增加了的、时间日期对象拷贝(如果参数是负数也能够有minus方法的效果)。
minus:返回一个时间减少了的、时间日期对象拷贝。
to:把当前时间日期对象转换成另外一个,可能会损失部分状态。
at:把这个对象与另一个对象组合起来,例如: date.atTime(time)。
format :根据某一个DateTimeFormatter格式化为字符串。

通过这一系列的方法,java.time完成了增加、减少、格式化、解析、提取等工作。
java.time包里面的类实例如果用了上面的方法而被修改了,那么会返回一个新的实例过来,而不像Calendar那样可以在同一个实例上进行不同的修改
以plus增加为例,简单来看一下

根据源码上的注释解释到,将此时间实例复制一份,把copy的实例作为基础将指定的小时数在这基础上计算增加,并返回一个新的实例。我们继续进去create中看一下怎么处理的

create方法我们注释都不用看的 return返回的是一个新创建的时间实例。ok,下面进入正题,开始整理具体的类与方法。

Instant :时间戳,相当于java.util的Date

Instant用于表示一个时间戳,它与我们常使用的System.currentTimeMillis()有些类似,不过Instant可以精确到纳秒(Nano-Second),System.currentTimeMillis()方法只精确到毫秒(Milli-Second)。如果查看Instant源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999999999)。Instant除了使用now()方法创建外,还可以通过ofEpochSecond方法创建:

Instant now = Instant.now();
System.out.println(now);
Instant instant = Instant.ofEpochSecond(60,1000000000);
System.out.println(instant);

ofEpochSecond()方法的第一个参数为秒,第二个参数为纳秒,上面的代码表示从1970-01-01 00:00:00开始后一分钟的一亿秒的时刻,控制台上的输出为:

2021-03-21T07:51:54.781Z
1970-01-01T00:01:01Z

LocalDateTime:包含日期和时间

获取当前时间

LocalDateTime now = LocalDateTime.now();
System.out.println(now);//2021-03-21T15:55:29.267

创建特定日期 (多种自定义) 比如:2021-03-20 09:00:00

LocalDateTime of = LocalDateTime.of(2021, 03, 20, 9, 00, 00);
System.out.println(of);//2021-03-20T09:00

获取获取年、月、日、时…信息 :

LocalDateTime now = LocalDateTime.now();
int year = now.getYear();//2021
System.out.println(year);
Month month = now.getMonth();//MARCH
int dayOfMonth = now.getDayOfMonth();//21
int hour = now.getHour();//16
int minute = now.getMinute();//8
int dayOfYear = now.getDayOfYear();//80
int second = now.getSecond();//32

LocalDate和LocalTime与LocalDateTime类似,不多说

日期增加、减少

LocalDateTime of = LocalDateTime.of(2020, 1, 1, 1, 1,1);
System.out.println(of);//2020-01-01T01:01:01
LocalDateTime nextYearTime = of.plusYears(1);
System.out.println(nextYearTime);//2021-01-01T01:01:01
LocalDateTime localDateTime = of.minusYears(1);
System.out.println(localDateTime);//2019-01-01T01:01:01

LocalDate和LocalTime与LocalDateTime类似,不多说

使用with方法设置月份

LocalDateTime of = LocalDateTime.of(2021, 2, 1, 1, 1,1);
LocalDateTime changeTime = of.withMonth(3);
System.out.println(changeTime);//2021-03-01T01:01:01

判断某个/当前年份是否闰年

LocalDate now = LocalDate.now();
System.out.println("isLeapYear :" + now.isLeapYear());//false
LocalDate of = LocalDate.of(2020, 1, 1);
System.out.println("isLeapYear :" + of.isLeapYear());//true

获取某个/当前日期时星期几

LocalDateTime now = LocalDateTime.now();
DayOfWeek dayOfWeek = now.getDayOfWeek();//SUNDAY

LocalDate与LocalDateTime类似,不多说

Duration : 计算两个“时间”的间隔

LocalDateTime from = LocalDateTime.of(2021, Month.JANUARY, 21, 15, 56, 0);    // 2019-01-21 15:56:00
 LocalDateTime to = LocalDateTime.of(2021, Month.FEBRUARY, 21, 15, 56, 0);     // 2019-02-21 15:56:00
Duration duration = Duration.between(from, to);     // 表示从 2021-01-21 15:56:00 到 2021-02-21 15:56:00
long days = duration.toDays();              // 这段时间的总天数
System.out.println(days);//31
long hours = duration.toHours();            // 这段时间的小时数
System.out.println(hours);//744
long minutes = duration.toMinutes();        // 这段时间的分钟数
System.out.println(minutes);//44640
long seconds = duration.getSeconds();       // 这段时间的秒数
System.out.println(seconds);//2678400
long milliSeconds = duration.toMillis();    // 这段时间的毫秒数
System.out.println(milliSeconds);//2678400000
long nanoSeconds = duration.toNanos();      // 这段时间的纳秒数
System.out.println(nanoSeconds);//2678400000000000

Duration对象还可以通过of()方法创建,该方法将一个时间段长度,和一个时间单位作为参数,多说无益看栗子(例子)吧

Duration duration1 = Duration.of(10, ChronoUnit.DAYS);       // 10天
System.out.println(duration1);//PT240H
Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS);  // 1000毫秒
System.out.println(duration2);//PT1S

Period : 用于计算两个“日期”的间隔

Period在概念上和Duration类似,区别在于Period是以年月日来衡量一个时间段

Period period = Period.between(LocalDate.of(2020, 1, 21),
                LocalDate.of(2021, 2, 21));
 int years = period.getYears();//1

ZoneId : 时区

获取所有合法的“区域/城市”字符串

Set<String> zoneIds = ZoneId.getAvailableZoneIds();//[Asia/Aden, America/Cuiaba, Etc/GMT+9,...]

获取系统默认时区

ZoneId systemZoneId = ZoneId.systemDefault();//Asia/Shanghai

创建时区

ZoneId zoneId = ZoneId.of("America/Cuiaba");//America/Cuiaba

判断两个日期是否相等

LocalDate of = LocalDate.of(2020, 01, 21);
 System.out.println(of.equals(LocalDate.now()));//false

检查类似生日这种周期性事件

类似每月账单、结婚纪念日、保险缴费日这些周期性事件。使用MonthDay类。这个类组合了月份和日,去掉 了年,这意味着你可以用它判断每年都会发生事件。

LocalDate dateOfBirth = LocalDate.of(1994, 11, 18);
MonthDay birthday = MonthDay.of(dateOfBirth.getMonth(), dateOfBirth.getDayOfMonth());
MonthDay currentMonthDay = MonthDay.from(LocalDate.now());
if(currentMonthDay.equals(birthday))
    System.out.println("Many Many happy returns of the day !!");
else
    System.out.println("Sorry, today is not your birthday");

//输出: Sorry, today is not your birthday

判断日期是早于还是晚于另一个日期

LocalDate tomorrow = LocalDate.of(2021, 4, 21);
System.out.println(tomorrow.isAfter(LocalDate.now()));//true

LocalDate yesterday = LocalDate.now().minus(1, ChronoUnit.DAYS);
System.out.println(yesterday.isBefore(LocalDate.now()));//true

java8中的时间类与Date类的相互转化

Instant instant  = Instant.now();
Date date = Date.from(instant);
Instant instant1 = date.toInstant();
System.out.println(instant1);//2021-03-21T09:00:41.950Z

Date date2 = new Date();
LocalDateTime localDateTime = LocalDateTime.ofInstant(date2.toInstant(), ZoneId.systemDefault());
System.out.println(localDateTime);//2021-03-21T17:00:42.005

LocalDateTime now = LocalDateTime.now();
Instant instant2 = now.atZone(ZoneId.systemDefault()).toInstant();
Date date3 = Date.from(instant2);
System.out.println(date3);//Sun Mar 21 17:00:42 CST 2021

LocalDate now1 = LocalDate.now();
Instant instant3 = now1.atStartOfDay().atZone(ZoneId.systemDefault()).toInstant();
Date date4 = Date.from(instant3);
System.out.println(date4);//Sun Mar 21 00:00:00 CST 2021

这里还是有必要解释一下下,LocalDate只是年月日不包含时分秒,所以转换后时分秒都是00

日期的格式化和解析DateTimeFormatter

  • Date转String
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("G yyyy年MM月dd号 E a hh时mm分ss秒");
String format = now.format(pattern);
System.out.println(format);//公元 2021年03月21号 星期日 下午 05时04分14秒
  • String转Date
DateTimeFormatter pattern = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
LocalDateTime dt = LocalDateTime.parse("2021-03-21 17:15:30",pattern);
System.out.println(dt.format(pattern));//2021-03-21 17:15:30

源码地址

以上是关于JAVA8 日期时间API整理的主要内容,如果未能解决你的问题,请参考以下文章

LocalDateTime JDK1.8

kaggle竞赛入门整理

Java8日期一文搞定Java8日期新特性

如何把年月日时分秒的字符串转换成日期类型

java 给固定日期(字符串)加上时分秒

iOS-24小时进制时分秒字符串转为时分字符串