Java8新特性总结 -6.Date/Time API

所有示例代码打包下载 : 点击打开链接

Java8新特性 : 
  1. 接口新增默认方法和静态方法
  2. Optional类
  3. Lambda表达式
  4. 方法引用
  5. Stream API - 函数式操作流元素集合
  6. Date/Time API
  7. 新API和工具
  8. Nashorn , JavaScript引擎

6 . Date/Time API

    在了解Java8的新Date/Time之前 , 先看一下之前的日期/时间存在哪些问题?
  • 非线程安全 − java.util.Date 是非线程安全的,所有的日期类都是可变的,这是Java日期类最大的问题之一。
  • 设计很差 − Java的日期/时间类的定义并不一致,在java.util和java.sql的包中都有日期类,此外用于格式化和解析的类在java.text包中定义。java.util.Date同时包含日期和时间,而java.sql.Date仅包含日期,将其纳入java.sql包并不合理。另外这两个类都有相同的名字,这本身就是一个非常糟糕的设计。
  • 时区处理麻烦 − 日期类并不提供国际化,没有时区支持,因此Java引入了java.util.Calendar和java.util.TimeZone类,但他们同样存在上述所有的问题。
    因为上面这些原因,诞生了第三方库Joda-Time,可以替代Java的时间管理API。Java 8中新的时间和日期管理API深受Joda-Time影响,并吸收了很多Joda-Time的精华。新的java.time包包含了所有关于日期、时间、时区、Instant(跟日期类似但是精确到纳秒)、duration(持续时间)和时钟操作的类。新设计的API认真考虑了这些类的不变性(从java.util.Calendar吸取的教训),如果某个实例需要修改,则返回一个新的对象。

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.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 . 
1 . java.time.LocalDate:

    LocalDate是一个不可变的类,它表示默认格式(yyyy-MM-dd)的日期,我们可以使用now()方法得到当前时间,也可以提供输入年份、月份和日期的输入参数来创建一个LocalDate实例。该类为now()方法提供了重载方法,我们可以传入ZoneId来获得指定时区的日期。该类提供与java.sql.Date相同的功能 . 

        LocalDate today = LocalDate.now();
        System.out.println("当前日期 : "+today);//2018-02-11
​
        LocalDate firstDay_2014 = LocalDate.of(2014, Month.JANUARY, 1);
        System.out.println("指定日期 : "+firstDay_2014);//2014-01-01
​
        LocalDate todayKolkata = LocalDate.now(ZoneId.of("Asia/Kolkata"));
        System.out.println("指定时区日期 : "+todayKolkata);//2018-02-11
​
        System.out.println("当前日期月份 : " + today.getMonth());//FEBRUARY
        System.out.println("一个月后的日期 : " + today.plusMonths(1));//2018-03-11
2 . java.time.LocalTime:
    LocalTime是一个不可变的类,它的实例代表一个符合人类可读格式的时间,默认格式是hh:mm:ss.zzz。像LocalDate一样,该类也提供了时区支持,同时也可以传入小时、分钟和秒等输入参数创建实例 . 
        LocalTime time = LocalTime.now();
        System.out.println("当前时间 : "+time);//11:47:05.472
​
        LocalTime specificTime = LocalTime.of(12,20,25,40);//12:20:25.000000040
        System.out.println("指定时间 : "+specificTime);
​
        LocalTime timeKolkata = LocalTime.now(ZoneId.of("Asia/Kolkata"));
        System.out.println("指定时区时间 : "+timeKolkata);// 09:17:05.473
​
        System.out.println("当前小时 : " + time.getHour());//11
        System.out.println("5小时后的时间 : " + time.plusHours(5));//16:48:36.472
3 . java.time.LocalDateTime:

    LocalDateTime是一个不可变的日期-时间对象,它表示一组日期-时间,默认格式是yyyy-MM-dd-HH-mm-ss.zzz。它提供了一个工厂方法,接收LocalDate和LocalTime输入参数,创建LocalDateTime实例

        LocalDateTime today = LocalDateTime.now();
        System.out.println("当前日期&时间 : "+today);//2018-02-11T11:52:06.398
​
        today = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        System.out.println("当前日期&时间 : "+today);//2018-02-11T11:52:06.399
​
        LocalDateTime specificDate = LocalDateTime.of(2014, Month.JANUARY, 1, 10, 10, 30);
        System.out.println("指定日期&时间 : "+specificDate);//2014-01-01T10:10:30
​
        LocalDateTime todayKolkata = LocalDateTime.now(ZoneId.of("Asia/Kolkata"));
        System.out.println("指定时区日期&时间 : "+todayKolkata);//2018-02-11T09:22:06.400
​
        System.out.println("当前日期&时间的月份 : " + today.getMonthValue());//2
        System.out.println("5天后的日期&时间 : " + today.plusDays(5));//2018-02-16T11:52:06.399
4 . java.time.Instant:
    Instant类是用在机器可读的时间格式上的,它以Unix时间戳的形式存储日期时间
        Instant timestamp = Instant.now();
        System.out.println("当前时间"+timestamp);
​
        Long currMills = timestamp.toEpochMilli();
        System.out.println("当前时间戳 : " + currMills);
        Instant specificTime = Instant.ofEpochMilli(currMills);
        System.out.println("时间戳转Instant : "+specificTime);
5 . 日期API工具:

    我们早些时候提到过,大多数日期/时间API类都实现了一系列工具方法,如:加/减天数、周数、月份数,等等。还有其他的工具方法能够使用TemporalAdjuster调整日期,并计算两个日期间的周期。

        LocalDate today = LocalDate.now();//今天日期
​
        System.out.println("年 : "+today.getYear()+"是否闰年 : "+today.isLeapYear());//2018 false
​
        System.out.println("今天是否在2015-01-01之前 : "+today.isBefore(LocalDate.of(2015,1,1)));//false
​
        System.out.println("拼接为日期&时间 : "+today.atTime(LocalTime.now()));//2018-02-11T12:01:42.816
​
        System.out.println("10天后的日期 : "+today.plusDays(10));//2018-02-21
        System.out.println("3周后的日期 : "+today.plusWeeks(3));//2018-03-04
        System.out.println("20个月之后的日期 : "+today.plusMonths(20));// 2019-10-11
​
        System.out.println("10天前的日期 : "+today.minusDays(10));//2018-02-01
        System.out.println("3周前的日期 : "+today.minusWeeks(3));//2018-01-21
        System.out.println("20个月之前的日期 : "+today.minusMonths(20));//2016-06-11
​
        System.out.println("本月第一天的日期 : "+today.with(TemporalAdjusters.firstDayOfMonth()));//2018-02-01
        LocalDate lastDayOfYear = today.with(TemporalAdjusters.lastDayOfYear());
        System.out.println("今年最后一天的日期 : "+lastDayOfYear);//2018-12-31
6 . DateTimeFormatter .
    解析和格式化:将一个日期格式转换为不同的格式,之后再解析一个字符串,得到日期时间对象,这些都是很常见的。对此Java8也提供了新的类DateTimeFormatter
        LocalDate date = LocalDate.now();
​
        System.out.println("默认格式日期 : "+date);//2018-02-11
​
        System.out.println("yyyy/MM/dd : " + date.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));//2018/02/11
        System.out.println("默认的ISO格式 : " + date.format(DateTimeFormatter.BASIC_ISO_DATE));//20180211
​
        LocalDateTime dateTime = LocalDateTime.now();
        System.out.println("默认日期&时间 : "+dateTime);//2018-02-11T12:10:44.149
        System.out.println("yyyy-MM-dd hh:mm:ss : " + dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));//2018-02-11 12::10::44
        System.out.println("默认的ISO格式 : " + dateTime.format(DateTimeFormatter.BASIC_ISO_DATE));//20180211
​
        Instant timestamp = Instant.now();
        System.out.println("默认时间戳 : "+timestamp);//2018-02-11T04:10:44.149Z
​
        LocalDateTime dt = LocalDateTime.parse("2008-08-08 20:08:08", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("字符串转日期 : "+dt);//2008-08-08T20:08:08
​
        Long longStamp = timestamp.toEpochMilli();
        DateTimeFormatter df= DateTimeFormatter.ofPattern("YYYY-MM-dd HH:mm:ss.SSS");
        String dateStr =  df.format(LocalDateTime.ofInstant(Instant.ofEpochMilli(longStamp), ZoneId.of("Asia/Shanghai")));
        System.out.println("long 转日期字符串 : " + dateStr);//2018-02-11 12:10:44.149 貌似更复杂了 ? 
7 . 旧的日期时间支持:

    旧的日期/时间类已经在几乎所有的应用程序中使用,因此做到向下兼容是必须的。这也是为什么会有若干工具方法帮助我们将旧的类转换为新的类,反之亦然。

        Instant timestamp = new Date().toInstant();//Date -> Instant
        LocalDateTime date = LocalDateTime.ofInstant(timestamp, ZoneId.of(ZoneId.SHORT_IDS.get("PST")));//Instant -> LocalDateTime
        System.out.println(date);
​
        Instant time = Calendar.getInstance().toInstant();//时间戳 -> Instant
        System.out.println(time);
        ZoneId defaultZone = TimeZone.getDefault().toZoneId();//TimeZone -> ZoneId
        System.out.println(defaultZone);
​
        ZonedDateTime gregorianCalendarDateTime = new GregorianCalendar().toZonedDateTime();//GregorianCalendar -> ZonedDateTime
        System.out.println(gregorianCalendarDateTime);
​
        Date dt = Date.from(Instant.now());// Instant -> Date
        System.out.println(dt);
​
        TimeZone tz = TimeZone.getTimeZone(defaultZone);//ZoneId -> TimeZone
        System.out.println(tz);
​
        GregorianCalendar gc = GregorianCalendar.from(gregorianCalendarDateTime);//ZonedDateTime -> GregorianCalendar
        System.out.println(gc);
8 . Clock : 

    它通过指定一个时区,然后就可以获取到当前的时刻,日期与时间。Clock可以替换System.currentTimeMillis()与TimeZone.getDefault()。

        Clock clock = Clock.systemUTC();
        System.out.println( clock.instant() );//2018-02-11T04:18:41.362Z
        System.out.println( clock.millis() );//1518322721440
9 . ZonedDateTime : 

    带时区日期时间处理

        ZonedDateTime now = ZonedDateTime.now();
        System.out.println("当前时区时间 : " + now);//2018-02-11T12:20:57.884+08:00[Asia/Shanghai]
        ZonedDateTime date1 = ZonedDateTime.parse("2007-12-03T10:15:30+05:30[Asia/Shanghai]");
        System.out.println("指定时区指定时间" + date1);//2007-12-03T10:15:30+08:00[Asia/Shanghai]
        ZoneId id = ZoneId.of("Europe/Paris");
        System.out.println("指定时区ZoneId: " + id);//Europe/Paris
        ZoneId currentZone = ZoneId.systemDefault();
        System.out.println("当前时区: " + currentZone);//Asia/Shanghai
10 . ChronoUnit : 

    可以代替Calendar的日期操作

        LocalDate today = LocalDate.now();
        System.out.println("当前日期 : " + today);//2018-02-11
        LocalDate nextWeek = today.plus(1, ChronoUnit.WEEKS);
        System.out.println("下周日期 : " + nextWeek);//2018-02-18
        LocalDate nextMonth = today.plus(1, ChronoUnit.MONTHS);
        System.out.println("下月日期 : " + nextMonth);//2018-03-11
        LocalDate nextYear = today.plus(1, ChronoUnit.YEARS);
        System.out.println("明年日期 : " + nextYear);//2019-02-11
        LocalDate nextDecade = today.plus(1, ChronoUnit.DECADES);
        LocalDate nextDecade20 = today.plus(2, ChronoUnit.DECADES);
        System.out.println("20年后日期: " + nextDecade20);//2038-02-11
11 . Period/Duration : 

    使用Java8中两个专门用来来处理时间差的类 .

  • Period - 处理有关基于时间的日期数量。
  • Duration - 处理有关基于时间的时间量。
    private static void testPeriod(){
        LocalDate date1 = LocalDate.now();
        System.out.println("当前日期 : " + date1);//2018-02-11
​
        LocalDate date2 = date1.plus(3, ChronoUnit.DAYS);
        System.out.println("3天后新日期 : " + date2);//2018-02-14
​
        Period period = Period.between(date1, date2);
        System.out.println("相差 : " + period);//P3D
        System.out.println("相差年份 : " + period.getYears());//0
        System.out.println("相差月份 : " + period.getMonths());//0
        System.out.println("相差天数 : " + period.getDays());//3
    }
​
    private static void testDuration(){
        LocalTime time1 = LocalTime.now();
        Duration twoHours = Duration.ofHours(2);
​
        System.out.println("2个小时的秒数 : " + twoHours.getSeconds());//7200
​
        LocalTime time2 = time1.plus(twoHours);
        System.out.println("2个小时后的新时间 : " + time2);//14:30:14.345
​
        Duration duration = Duration.between(time1, time2);
        System.out.println("相差: " + duration);//PT2H
        System.out.println("相差秒数 : " + duration.getSeconds());//7200
    }
12 . TemporalAdjuster :
    是做日期数学计算 . 这个类在日期调整时非常有用,比如得到当月的第一天、最后一天,当年的第一天、最后一天,下一周或前一周的某天等。
        LocalDate date1 = LocalDate.now();
        System.out.println("当前日期 : " + date1);//2018-02-11
​
        LocalDate nextTuesday = date1.with(TemporalAdjusters.next(DayOfWeek.TUESDAY));
        System.out.println("下一个周二 : " + nextTuesday);//2018-02-13
​
        LocalDate firstInMonth = LocalDate.of(date1.getYear(), date1.getMonth(), 1);
        LocalDate secondSaturday = firstInMonth.with(
                TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)).with(
                TemporalAdjusters.next(DayOfWeek.SATURDAY));
        System.out.println("当月的第二个周六 : " + secondSaturday);//2018-02-10

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值