java8 时间戳 相减_jdk8新特性之八日期时间API

引言

java 8通过发布新的Date-Time API进一步加强对日期与时间的处理。在旧版的java中,日期时间APi存在诸多问题。java 8引入的新的一系列API,对时间日期处理提供了更好的支持,清楚的定义了时间日期的一些概念,比如说,瞬时时间(Instant),持续时间(duration),日期(date),时间(time),时区(time-zone)以及时间段(Period)。同时,借鉴了Joda库的一些优点,比如将人和机器对时间日期的理解区分开的。

java8新特性

旧版日期时间API的问题

非线程安全:java.uttil.Date 是非线程安全的,所有的日期类都是可变的,这是java日期类最大的问题之一。

设计很差:java的日期/时间类的定义并不一致,在java.util和java.sql的包中毒有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同提高的名字,这本身就是一个非常糟糕的设计。

时区处理麻烦:日期类并不提供国际化,没有时区支持,因此java引入了java.util.Caleandar和java.util.TimeZone类,但他们同样存在上述所有的问题。

新日期时间API

java8在java.time包下提供了很多新的API。以下为两个比较重要的API:

Local(本地):简化了日期时间的处理,没有时区的问题。

Zoned(时区):通过制定的时区处理日期时间。 具体的API:

LocalDate:存储不包含时间的日期,比如2020-01-11。可以用来存储生日,周年纪念日,入职日期等。

LocalTime:存储不包含日期的时间,比如11:07:03.580。

LocalDate-日期

只存储年月日。格式:2020-01-11

创建LocalDate对象

//获取当前日期

LocalDate currDate=LocalDate.now();

System.out.println("当前日期:"+currDate);

//指定日期

LocalDate noeDay=LocalDate.of(2020, 1, 11);

System.out.println("当前日期:"+noeDay);

//通过字符串指定日期

LocalDate towDay=LocalDate.parse("2020-01-11");

System.out.println("当前日期:"+towDay);

运行结果输出:

当前日期:2020-01-11

当前日期:2020-01-11

当前日期:2020-01-11

获取年月日周

// 年

int year = currDate.getYear();

// 月

int month = currDate.getMonthValue();

// 一月的第几天

int day = currDate.getDayOfMonth();

// 一周的第几天

int week = currDate.getDayOfWeek().getValue();

System.out.printf("%d年%d月%d日,星期%d%n", year, month, day, week);

运行结果输出:

2020年1月11日,星期6

比较两个日期是否相同

LocalDate重写了equals方法,让日期的比较也变得简单了。

LocalDate date1 = LocalDate.parse("2020-01-11");

LocalDate date2 = LocalDate.parse("2020-01-11");

System.out.println("比较两个日期是否相同:"+date1.equals(date2));

运行结果输出:

比较两个日期是否相同:true

日期前后比较

//isBefore在之前

boolean isBefore=LocalDate.parse("2020-01-11").isBefore(LocalDate.parse("2020-01-10"));

//isAfter在之后

boolean isAfter=LocalDate.parse("2020-01-11").isAfter(LocalDate.parse("2020-01-10"));

日期加减

System.out.println("当前时间"+LocalDate.now());

System.out.println("当前时间加1天"+LocalDate.now().plusDays(1));

System.out.println("当前时间加1月"+LocalDate.now().plusMonths(1));

System.out.println("当前时间加1年"+LocalDate.now().plusYears(1));

运行结果输出:

当前时间2020-01-11

当前时间加1天2020-01-12

当前时间加1月2020-02-11

当前时间加1年2021-01-11

LocalTime-时间

存储不包含日期的时间,比如11:07:03.580。

LocalTime和LocalDate类似,区别在于LocalDate不包含具体时间,而LocalTime包含具体时间。同样可以使用now、of或parse方法来获得对象。

LocalTime time = LocalTime.now();

LocalTime time2 =LocalTime.of(11, 7,3);

LocalTime time3 =LocalTime.parse("11:07:03");

LocalDate类似它也拥有isBefore、isAfter、获取时间单元等方法,就不再赘述。

需要注意的是,LocalTime获得的时间格式为:11:41:58.904。也就是,HH:mm:ss.nnn,这里nnn是纳秒。

还有一个在实战中查询日期区间时我们经常定义的“23:59:59.99”常量再也不用自己定义了。

//最大时间23:59:59.999999999

LocalTime maxTime =LocalTime.MAX;

//最小时间00:00

LocalTime minTime =LocalTime.MIN;

LocalDateTime-日期和时间的组合

LocalDateTime表示日期和时间组合。同样可以使用now、of或parse方法来获得对象。

LocalDateTime datetime=LocalDateTime.now();

LocalDateTime datetime2=LocalDateTime.of(2020, 1,11,11,54,30);

LocalDateTime datetime3=LocalDateTime.parse("2020-01-11T12:35");

也可以调用LocalDate的atTime()方法或LocalTime的atDate()方法将LocalDate或LocalTime合并成一个LocalDateTime。

LocalDateTime datetime4=LocalDate.now().atTime(LocalTime.now());

LocalDateTime datetime5=LocalTime.now().atDate(LocalDate.now());

LocalDateTime与LocalDate和LocalTime之间可以相互转化。其他日期增减等操作与上面的类似。

Instant-时间戳

用于“时间戳”的运算。它是以Unix元年(传统的设定为UTC时区1970年1月1日午夜时分)开始所经历的描述进行运算。

// 默认获取UTC时区

Instant instant=Instant.now();

System.out.println("当前时间(UTC时区):"+instant);

System.out.println("获取时间戳:"+instant.toEpochMilli());

// 偏移量运算

OffsetDateTime offsetDateTime =instant.atOffset(ZoneOffset.ofHours(8));

System.out.println("当前时间:"+offsetDateTime);

// 以Unix元年为起点,进行偏移量运算

Instant instant2 = Instant.ofEpochSecond(60);

System.out.println(instant2);

运行结果输出为:

当前时间(UTC时区):2020-01-11T05:55:35.493Z

获取时间戳:1578722135493

当前时间:2020-01-11T13:55:35.493+08:00

1970-01-01T00:01:00Z

Duration-获取时间段

Duration的内部实现与Instant类似,但Duration表示时间段,通过between方法创建。

LocalDateTime from = LocalDateTime.now();

LocalDateTime to = LocalDateTime.now().plusDays(1);

Duration duration=Duration.between(from, to);

//总天数

long days=duration.toDays();

//小时

long hours=duration.toHours();

//分钟

long millis=duration.toMillis();

//秒数

long seconds=duration.getSeconds();

//毫秒数

long minutes=duration.toMinutes();

//纳秒数

long nanos=duration.toNanos();

System.out.println("天数"+days);

System.out.println("小时"+hours);

System.out.println("分钟"+millis);

System.out.println("秒数"+seconds);

System.out.println("毫秒数"+minutes);

System.out.println("纳秒数"+nanos);

运行结果输出:

天数1

小时24

分钟86400000

秒数86400

毫秒数1440

纳秒数86400000000000

Duration对象还可以通过of()方法创建,该方法参数为时间段长度和时间单位。

// 7天

Duration duration1 = Duration.of(7, ChronoUnit.DAYS);

// 60秒

Duration duration2 = Duration.of(60, ChronoUnit.SECONDS);

Period-获取日期段

Period与Duration类似,获取一个时间段,只不过单位为年月日,也可以通过of方法和between方法创建,between方法接收的参数为LocalDate。

Period period=Period.of(2020, 1, 11);

Period period1 = Period.between(LocalDate.now(), LocalDate.now().plusYears(1));

ZonedDateTime-创建时区时间

ZonedDateTime类,用于处理带时区的日期和时间。ZoneId表示不同的时区。大约有40不同的时区。

Set allZoneIds=ZoneId.getAvailableZoneIds();

创建时区:

ZoneId zoneId=ZoneId.of("Asia/Shanghai");

把LocalDateTime转换成特定的时区:

ZonedDateTime zonedDateTime=ZonedDateTime.of(LocalDateTime.now(), zoneId);

获取当前时区:

//获取当前时区

ZoneId z=ZoneId.systemDefault();

获取日期时间:

ZonedDateTime dd = ZonedDateTime.now();

ZonedDateTime date1 = ZonedDateTime.parse("2015-12-03T10:15:30+05:30[Asia/Shanghai]");

时间日期格式化

Java8对日期的格式化操作非常简单,首先看到上面的类大多都提供了parse方法,可以直接通过解析字符串得到对应的对象。

而日期和时间的格式化可通过LocalDateTime的format方法进行格式化。

LocalDateTime dateTime=LocalDateTime.now();

String str=dateTime.format(DateTimeFormatter.ISO_DATE_TIME);

System.out.println(str);

str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));

System.out.println(str);

可以使用DateTimeFormatter预置的格式,也可以通过DateTimeFormatter.ofPattern方法来指定格式。

关于阿丹博客

以上内容,纯属一家之言,因个人能力有限,难免有疏漏和错误之处,如发现 bug 或者有更好的 建议,欢迎留言批评指正,不吝感激。 下面阿丹的个人博客,记录所有学习和工作中的博文,欢迎大家前去逛逛。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值