Java8新的时间和日期

Java 8日期/时间API

Java 8日期/时间API是JSR-310的实现,它的实现目标是克服旧的日期时间实现中所有的缺陷,新的日期/时间API的一些设计原则是:

  • 不变性:新的日期/时间API中,所有的类都是不可变的,这对多线程环境有好处。
    关注点分离:新的API将人可读的日期时间和机器时间(unix timestamp)明确分离,它为日期(Date)、时间(Time)、日期时间(DateTime)、时间戳(unix timestamp)以及时区定义了不同的类。

  • 清晰:在所有的类中,方法都被明确定义用以完成相同的行为。举个例子,要拿到当前实例我们可以使用now()方法,在所有的类中都定义了format()和parse()方法,而不是像以前那样专门有一个独立的类。为了更好的处理问题,所有的类都使用了工厂模式和策略模式,一旦你使用了其中某个类的方法,与其他类协同工作并不困难。

  • 实用操作:所有新的日期/时间API类都实现了一系列方法用以完成通用的任务,如:加、减、- - 格式化、解析、从日期/时间中提取单独部分,等等。

  • 可扩展性:新的日期/时间API是工作在ISO-8601日历系统上的,但我们也可以将其应用在非IOS的日历上。

Java日期/时间API包

Java日期/时间API包含以下相应的包。

  • java.time包:这是新的Java日期/时间API的基础包,所有的主要基础类都是这个包的一部分,如:LocalDate, LocalTime, LocalDateTime, Instant, Period, Duration等等。所有这些类都是不可变的和线程安全的,在绝大多数情况下,这些类能够有效地处理一些公共的需求。

  • java.time.chrono包:这个包为非ISO的日历系统定义了一些泛化的API,我们可以扩展AbstractChronology类来创建自己的日历系统。

  • java.time.format包:这个包包含能够格式化和解析日期时间对象的类,在绝大多数情况下,我们不应该直接使用它们,因为java.time包中相应的类已经提供了格式化和解析的方法。

  • java.time.temporal包:这个包包含一些时态对象,我们可以用其找出关于日期/时间对象的某个特定日期或时间,比如说,可以找到某月的第一天或最后一天。你可以非常容易地认出这些方法,因为它们都具有“withXXX”的格式。

  • java.time.zone包:这个包包含支持不同时区以及相关规则的类。

Java日期/时间API示例

java8引入了一套全新的时间日期API。
ava。time包中的是类是不可变且线程安全的。新的时间及日期API位于java.time中,下面是一些关键类

  • Instant——它代表的是时间戳

  • LocalDate——不包含具体时间的日期,比如2014-01-14。它可以用来存储生日,周年纪念日,入职日期等。

  • LocalTime——它代表的是不含日期的时间

  • LocalDateTime——它包含了日期及时间,不过还是没有偏移信息或者说时区。

  • ZonedDateTime——这是一个包含时区的完整的日期时间,偏移量是以UTC/格林威治时间为基准的。
    这里写图片描述

方法概览

该包的API提供了大量相关的方法,这些方法一般有一致的方法前缀:

  • of:静态工厂方法。

  • parse:静态工厂方法,关注于解析。

  • get:获取某些东西的值。

  • is:检查某些东西的是否是true。

  • with:不可变的setter等价物。

  • plus:加一些量到某个对象。

  • minus:从某个对象减去一些量。

  • to:转换到另一个类型。

  • at:把这个对象与另一个对象组合起来,例如: date.atTime(time)。

与旧的API对应关系

这里写图片描述

java8是如何处理时间及日期的

获取当天的日期


    @Test
    public void getNow() {
        LocalDate now = LocalDate.now();// 取当前日期
        LocalDate localDate = LocalDate.of(2017, 6, 1);// 根据年月日取日期,12月就是12:
        LocalDate endOfFeb = LocalDate.parse("2014-02-28");
        localDate.getYear();//年
        localDate.getMonth();//月
        localDate.getDayOfMonth();//日
        localDate.getDayOfYear();//年中的第几天
    }

何判断某个日期在另一个日期的前面还是后面


    @Test
    public void operation() {
        LocalDate date = LocalDate.now();// 取当前日期
        date.plusDays(1);//时间加1天
        date.minusDays(1);

        date.plusWeeks(1);//加1个星期
        date.minusWeeks(1);

        date.plusMonths(1);
        date.minusMonths(1);

        date.plusYears(1);//加1年
        date.minusYears(1);

        date.plus(1, ChronoUnit.DAYS);//等同于   date.plusDays(1);//时间加1天
        date.minus(1, ChronoUnit.DAYS);

        LocalDate localDate = LocalDate.of(2017, 6, 1);

        LocalDateTime localDateTime = LocalDateTime.now();

    }

如何在java8中检查闰年


        LocalDateTime localDateTime = LocalDateTime.now();

        localDate.isLeapYear();//是否是闰年

如何检查重复事件,比如说生日

在Java中还有一个与时间日期相关的实际任务就是检查重复事件,比如说每月的帐单日,结婚纪念日,每月还款日或者是每年交保险费的日子。如果你在一家电商公司工作的话,那么肯定会有这么一个模块,会去给用户发送生日祝福并且在每一个重要的假日给他们捎去问候,比如说圣诞节,感恩节,在印度则可能是万灯节(Deepawali)。如何在Java中判断是否是某个节日或者重复事件?使用MonthDay类。这个类由月日组合,不包含年信息,也就是说你可以用它来代表每年重复出现的一些日子。当然也有一些别的组合,比如说YearMonth类。它和新的时间日期库中的其它类一样也都是不可变且线程安全的,并且它还是一个值类(value class)。我们通过一个例子来看下如何使用MonthDay来检查某个重复的日期:

    @Test
    public void MonthDay() {
        LocalDate localDate = LocalDate.now();
        MonthDay monthDay = MonthDay.of(7, 18);
        MonthDay day = MonthDay.from(localDate);
        if (monthDay.equals(day)) {
            System.out.println("Many Many happy returns of the day !!");
        } else {
            System.out.println("Sorry, today is not your birthday");

        }

    }

两个日期之间包含多少天,多少个月

还有一个常见的任务就是计算两个给定的日期之间包含多少天,多少周或者多少年。你可以用java.time.Period类来完成这个功能。在下面这个例子中,我们将计算当前日期与将来的一个日期之前一共隔着几个月。

    @Test
    public void period() {
        LocalDate localDate = LocalDate.now();
        LocalDate of = LocalDate.of(2016, 7, 19);
        Period between = Period.between(localDate, of);
        between.getDays();
        between.getMonths();
        between.getYears();
    }

处理不同的时区

java8中不仅将日期和时间进行了分离,同时还有时区。比如ZonId代表的是某个特定时区,ZonedDateTime代表带时区的时间,等同于以前的GregorianCalendar类。使用该类,可以将本地时间转换成另一个时区中的对应时间。

    @Test
    public void Zoneld() {
        LocalDateTime localDateTime = LocalDateTime.now();
        ZoneId zoneId = ZoneId.systemDefault();
        ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
        ZonedDateTime zonedDateTime1 = ZonedDateTime.of(localDateTime, zoneId);
    }

日期转换经常遇到

    @Test
    public void with() {
        LocalDate today = LocalDate.now();
        // 取本月第1天:
        LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2014-12-01
// 取本月第2天:
        LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2014-12-02
// 取本月最后一天,再也不用计算是28,29,30还是31:
        LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2014-12-31
// 取下一天:
        LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 变成了2015-01-01
// 取2015年1月第一个周一,这个计算用Calendar要死掉很多脑细胞:
        LocalDate firstMondayOf2015 = LocalDate.parse("2015-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2015-01-05
    }

清除毫秒数

LocalTime now = LocalTime.now().withNano(0)); // 11:09:09

带时区偏移量的日期与时间

在Java 8里面,你可以用ZoneOffset类来代表某个时区,比如印度是GMT或者UTC5:30,你可以使用它的静态方法ZoneOffset.of()方法来获取对应的时区。只要获取到了这个偏移量,你就可以拿LocalDateTime和这个偏移量创建出一个OffsetDateTime。

LocalDateTime datetime = LocalDateTime.of(2014, Month.JANUARY, 14, 19, 30); 
ZoneOffset offset = ZoneOffset.of("+05:30"); 
OffsetDateTime date = OffsetDateTime.of(datetime, offset); 
System.out.println("Date and Time with timezone offset in Java : " + date); 

Output : 
Date and Time with timezone offset in Java : 2014-01-14T19:30+05:30

使用预定义的格式器来对日期进行解析/格式化

在java8之前,时间日期的格式化非常麻烦,经常使用SimpleDateFormat来进行格式化,但是SimpleDateFormat并不是线程安全的。在java8中,引入了一个全新的线程安全的日期与时间格式器。并且预定义好了格式。

    @Test
    public void parse2() {
        String date = "2017-07-17";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(date, dateTimeFormatter);
    }

使用自定义的格式器来解析日期

在上例中,我们使用了预置的时间日期格式器来解析日期字符串了,但是有时预置的不能满足的时候就需要我们自定义日期格式器了,下面的例子中的日期格式是”MM dd yyyy”.你可以给DateTimeFormatter的ofPattern静态方法()传入任何的模式,它会返回一个实例,这个模式的字面量与前例中是相同的。比如M代表月,m仍代表分,无效的模式会抛异常DateTimeParseException。

    @Test
    public void formatter() {
        String date = "2017-07-17";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate localDate = LocalDate.parse(date, dateTimeFormatter);
    }

对日期进行格式化,转换成字符串

前面的两个例子中,我们主要是对日期字符串来进行解析转换成日期,在这个例子我们相反,是把日期转换成字符。这里我们有个LocalDateTime类的实例,我们要把他转换成一个格式化好的日期串,与前例相同的是,我们仍需要制定模式串去创建一个DateTimeFormatter类的实例,但调用的是LocalDate.format()。这个方法会返回一个代表当前日期的字符串,对应的模式就是传入的DateTimeFormatter实例中定义好的。


    @Test
    public void formatter() {
        LocalDate localDate = LocalDate.now();
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        String format = localDate.format(dateTimeFormatter);
    }
  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值