乐趣区

Java-8-时间日期-API

Java 8 时间日期 API

Java 8 中新的时间与日期 API 中的所有类都是不可变且线程安全的,任何修改操作都会返回一个新的实例,而之前 java.util.Date、Calendar 以及 SimpleDateFormat 这些关键的类都不是线程安全的。

java 8 对 时间 api 重新进行了设计,常用的有以下几种类。

         /***
          * LocalDate:表示不带时间的日期
          * LocalTime:表示不带日期的时间
          * LocalDateTime:日期和时间类
          * ZoneId:时区
          * ZonedDateTime:一个带时区的完整时间
          * Instant:Unix 时间,它代表的是时间戳,比如 2018-01-14T02:20:13.592Z
          * Clock:获取某个时区下当前的瞬时时间,日期或者时间
          * Duration:表示一个绝对的精确跨度,使用毫秒为单位
          * Period:这个类表示与 Duration 相同的概念,但是以人们比较熟悉的单位表示,比如年、月、周
          * DateTimeFormatter:格式化输出
          * TemporalAdjusters:获得指定日期时间等,如当月的第一天、今年的最后一天等
          * 
          */

方法

         /**
          * of:静态工厂方法,用于创建实例
          * now:静态工厂方法,用当前时间创建实例
          * parse:静态工厂方法,从字符串解析得到对象实例
          * get:获取时间日期对象的部分状态。* is:检查某些东西的是否是 true,例如比较时间前后
          * with:返回一个部分状态改变了的时间日期对象拷贝
          * plus:返回一个时间增加了的、时间日期对象拷贝
          * minus:返回一个时间减少了的、时间日期对象拷贝
          * to:转换到另一个类型
          * at:把这个对象与另一个对象组合起来,例如 date.atTime(time)
          * format:提供格式化时间日期对象的能力
          *
          */

LocalDate

         /**
          *LocalDate
          */
         //LocalDate 是用来表示无时间的日期的,也不附带任何与时区相关的信息
         LocalDate today = LocalDate.now();
         System.out.println("今日日期:"+ today);
         // 它提供 plus()/minus() 方法可以用来增加减少日、星期或者月,ChronoUnit 则用来表示这个时间单位。// 这些方法返回的是一个新的 LocalDate 实例的引用,因为 LocalTime 是不可变的,// 任何修改操作都会返回一个新的实例。LocalDate localDate = today.plusDays(1);

         // 等价于  today.plus(1, ChronoUnit.DAYS);
         System.out.println("明日日期:"+ localDate);

         // 日期减法
         LocalDate today1 = localDate.minus(1, ChronoUnit.DAYS);
         System.out.println("今日日期:" + today1);

LocalTime、LocalDateTime


         LocalTime time = LocalTime.now();
         System.out.println("现在的时间:" + time);
         // 小时
         int hour = time.getHour();
         System.out.println(hour);
         OffsetTime offsetTime = time.atOffset(ZoneOffset.UTC);
         System.out.println("UTC 时间:"+offsetTime);


         /**
          *
          */
         // 系统默认时间
         LocalTime time2 = LocalTime.now(Clock.systemDefaultZone());
         System.out.println("系统默认时间 :"+time2);


         LocalDate date =LocalDate.now();
         //LocalDateTime 将 LocalDate 和 LocalTime 结合起来
         LocalDateTime localDateTime = LocalDateTime.of(today,time2);
         System.out.println("LocalDateTime 将 LocalDate 和 LocalTime 结合起来 :" + localDateTime);

         //
         LocalDate localDate1 = LocalDate.of(2018, 11, 11);
         System.out.println("localDate1 自定义日期:" + localDate1);

         LocalTime localTime2 = LocalTime.of(12, 11, 11);
         LocalTime localTime3 = LocalTime.of(12, 12, 12, 12);
         System.out.println("LocalTime 自定义时间:" + localTime2);
         System.out.println("LocalTime 自定义时间带纳秒:" + localTime3);

DateTimeFormatter

         格式化与解析时间对象 DateTimeFormatter
        格式器用于解析日期字符串和格式化日期输出,创建格式器最简单的方法是通过 DateTimeFormatter 的静态工厂方法以及常量。
      
        //1 自定义字母模式解析
         DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy/MM/dd");
         String format = localDate1.format(dateTimeFormatter);
         System.out.println(format);
         

         //2 常用 ISO 格式常量,如 ISO_LOCAL_DATE
          dateTimeFormatter = DateTimeFormatter.ISO_DATE;
          format = localDate1.format(dateTimeFormatter);
          System.out.println(format);

          //3 本地化样式,如 ofLocalizedDate(FormatStyle.MEDIUM)
         dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL);
         format = localDate1.format(dateTimeFormatter);
         System.out.println("FormatStyle.FULL ="+ format);//2018 年 11 月 11 日 星期日

         dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM);
         format = localDate1.format(dateTimeFormatter);
         System.out.println("FormatStyle.MEDIUM =" + format);//2018-11-11

         dateTimeFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG);
         format = localDate1.format(dateTimeFormatter);
         System.out.println("FormatStyle.LONG ="+ format);//2018-11-11


        // 将日期格式化指定格式
         String format1 = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy,MM,dd"));
         System.out.println(format1);//2019,08,25

字符串格式化成日期

         LocalDate parse = LocalDate.parse("2019-10-10");
         System.out.println("默认:" + parse);
          //parse = LocalDate.parse("2019/8/10");// 异常
         /**   默认的解析格式是 -
          *     public static final DateTimeFormatter ISO_LOCAL_DATE;
          *     static {*         ISO_LOCAL_DATE = new DateTimeFormatterBuilder()
          *                 .appendValue(YEAR, 4, 10, SignStyle.EXCEEDS_PAD)
          *                 .appendLiteral('-')
          *                 .appendValue(MONTH_OF_YEAR, 2)
          *                 .appendLiteral('-')
          *                 .appendValue(DAY_OF_MONTH, 2)
          *                 .toFormatter(ResolverStyle.STRICT, IsoChronology.INSTANCE);
          *     }
          */
         //System.out.println("默认:" + parse);

         // 所以对于 "2019/8/10" 格式 我们需要自定义 解析格式
         // 注意 2019/08/10 不能写成 2019/8/10,不然会抛出异常
         parse = LocalDate.parse("2019/08/10",DateTimeFormatter.ofPattern("yyyy/MM/dd"));
         System.out.println(parse); //2019-08-10

         // 自定义解析格式
           dates = LocalDate.parse("20190825",
                 DateTimeFormatter.ofPattern("yyyyMMdd"));
         System.out.println(dates);//2019-08-25

         dates = LocalDate.parse("2019/08/25",
                 DateTimeFormatter.ofPattern("yyyy/MM/dd"));
         System.out.println(dates);//2019-08-25



     // 25/08/2019 - > 2019/08/25
         LocalDate parse2 = LocalDate.parse("25/08/2019",DateTimeFormatter.ofPattern("dd/MM/yyyy"));
         String format2 = parse2.format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
         System.out.println(format2);//2019/08/25



         LocalDate parse2 = LocalDate.parse("25/08/2019",DateTimeFormatter.ofPattern("dd/MM/yyyy"));
         System.out.println(parse2);//2019-08-25

Duration 与 Period

Duration 表示一个时间段,Duration 包含两部分:seconds 表示秒,nanos 表示纳秒,它们的组合表达了时间长度。因为 Duration 表示时间段,所以 Duration 类中不包含 now() 静态方法。注意,Duration 不包含毫秒这个属性。
  

         LocalDateTime from =LocalDateTime.of(2019,8,11,11,11,11,11);
         LocalDateTime to =LocalDateTime.of(2019,8,10,10,10,10,10);
         Duration between = Duration.between(from, to);
         long l = between.toDays();
         System.out.println("相差天数 =" + l); // -1
         long l1 = between.toHours();
         System.out.println(l);// -1
         long l2 = between.toMinutes();
         System.out.println(l);// -1
         long l3 = between.toMillis();
         System.out.println(l);// -1
         long l4 = between.toNanos();
         System.out.println(l);// -1

Period 在概念上和 Duration 类似,区别在于 Period 是以年月日来衡量一个时间段。
Duration 用于计算两个时间间隔,Period 用于计算两个日期间隔,所以 between() 方法只能接收 LocalDate 类型的参数。

         Period of1 = Period.of(2019, 10, 10);
         Period of2 = Period.of(2018, 9, 9);
         System.out.println(of1);//P2019Y10M10D

         LocalDate from1 =LocalDate.of(2019,8,11);
         LocalDate to2 =LocalDate.of(2018,8,10);
         Period between1 = Period.between(from1, to2);
         //Period 得到的是差值的绝对值
         System.out.println("相差年:" + between1.getYears());//-1
         System.out.println("相差月:" + between1.getMonths());//0
         System.out.println("相差日:" + between1.getDays());//-1


         // 计算两个时间的区间距离呢
         long year = from1.until(to2, ChronoUnit.YEARS);//-1
         long month = from1.until(to2, ChronoUnit.MONTHS);//-12
         long month1 = to2.until(from1, ChronoUnit.MONTHS);//12
         System.out.println(year);
         System.out.println(month);
         System.out.println("正值" + month1);

Instant 与 Clock

         // 加 1s
         Instant instant1 = Instant.ofEpochSecond(1);
         System.out.println(instant1);//1970-01-01T00:00:01Z

         // 加 10 毫秒
         Instant instant2 = Instant.ofEpochMilli(10);
         System.out.println(instant2);//1970-01-01T00:00:00.010Z

         // 当前时间 从 1970-1- 1 号到现在的时间 相当于 new Date()
         Instant instant = Instant.now();
         // 秒  = 2019-08-24T14:49:36.344Z
         System.out.println("秒  =" + instant);

         //new Date() 转为 Instant
         Instant instant3 = new Date().toInstant();
         System.out.println("与 new Date() 转换" + instant3);//2019-08-24T14:57:07.464Z

         // 解析时间
         Instant parse1 = Instant.parse("2019-08-24T14:59:16.708Z");
         System.out.println(parse1);
         // 加 10 天
         Instant plus = parse1.plus(10, ChronoUnit.DAYS);
         //2019-09-03T14:59:16.708Z
         System.out.println(plus);

      Clock 是时钟系统,用于查找当前时刻。你可以用它来获取某个时区下当前的日期或者时间。可以用 Clock 来替代旧的 System.currentTimeInMillis() 与 TimeZone.getDefault() 方法。
            // 世界协调时 UTC
         Clock clock = Clock.systemUTC();
         System.out.println(clock.getZone());// time-zone  Z
         // 获取 clock 对应的毫秒数,与 System.currentTimeMillis() 输出相同
         System.out.println(clock.millis());//



         // 通过 Clock 获取当前时刻
         System.out.println("通过 Clock 获取当前时刻" + clock.instant());//


         // 默认时区时间
         Clock clock1 = Clock.systemDefaultZone();
         System.out.println(clock1.instant());

         // 自定义时区
         Clock clock2 = clock1.withZone(ZoneId.of("Asia/Shanghai"));
         Instant instant4 = clock2.instant();
         System.out.println(instant4);
        // 纽约时间
         Clock clock3 = Clock.system(ZoneId.of("America/New_York"));
         System.out.println("纽约时间:" + LocalDateTime.now(clock3));
         // 不能用 .instant() 输出 此输出是系统默认时间
         //System.out.println(clock3.instant());



         // 当前时区加上 100s
         Clock offset = Clock.offset(clock, Duration.ofSeconds(100));
         System.out.println(offset.instant());

ZoneId 和 ZonedDateTime

        
           // 默认时区时间
         ZonedDateTime now = ZonedDateTime.now();
         LocalDate localDate2 = now.toLocalDate();
         System.out.println(localDate2);//2019-08-24

         // 特定时区下的日期和时间
         ZonedDateTime Shanghai = ZonedDateTime.of(LocalDateTime.now(), ZoneId.of("Asia/Shanghai"));
         System.out.println(Shanghai);//2019-08-24T23:22:31.149+08:00[Asia/Shanghai]

         ZonedDateTime Tokyo = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
         System.out.println(Tokyo);//2019-08-25T00:26:51.690+09:00[Asia/Tokyo]

         ZoneId america = ZoneId.of("America/New_York");
         System.out.println(ZonedDateTime.now(america));//2019-08-24T11:28:48.430-04:00[America/New_York]
使用 TemporalAdjuster 类灵活操纵日期

有的时候,你需要进行一些更加复杂的日期操作,比如,将日期调整到下个周日、下个工作日,或者是本月的最后一天。这时,你可以使用重载版本的 withXXX 方法,向其传递一个提供了更多定制化选择的 TemporalAdjuster 对象,更加灵活地处理日期。对于最常见的用例,日期和时间 API 已经提供了大量预定义的 TemporalAdjuster。你可以通过 TemporalAdjuster 类的静态工厂方法访问它们。

TemporalAdjuster 类中的常用工厂方法
  • dayOfWeekInMonth 创建一个新的日期,它的值为同一个月中每一周的第几天
  • firstDayOfMonth 创建一个新的日期,它的值为当月的第一天
  • firstDayOfNextMonth 创建一个新的日期,它的值为下月的第一天
  • firstDayOfNextYear 创建一个新的日期,它的值为明年的第一天
  • firstDayOfYear 创建一个新的日期,它的值为当年的第一天
  • firstInMonth 创建一个新的日期,它的值为同一个月中,第一个符合星期几要求的值 -
  • lastDayOfMonth 创建一个新的日期,它的值为当月的最后一天
  • lastDayOfNextMonth 创建一个新的日期,它的值为下月的最后一天
  • lastDayOfNextYear 创建一个新的日期,它的值为明年的最后一天
  • lastDayOfYear 创建一个新的日期,它的值为今年的最后一天
  • lastInMonth 创建一个新的日期,它的值为同一个月中,最后一个符合星期几要求的值
  • next/previous 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星 期几要求的日期
  • nextOrSame/previousOrSame 创建一个新的日期,并将其值设定为日期调整后或者调整前,第一个符合指定星 期几要求的日期,如果该日期已经符合要求,直接返回该对象

        // 当月中 第二周 的周一
         TemporalAdjuster temporalAdjuster1 = TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.MONDAY);
         LocalDate with = LocalDate.now().with((temporal) -> temporal.with(temporalAdjuster1));
         System.out.println(with);//2019-08-12

         //firstDayOfMonth  当月的第一天
         TemporalAdjuster temporalAdjuster2 = TemporalAdjusters.firstDayOfMonth();
          with = LocalDate.now().with((temporal) -> temporal.with(temporalAdjuster2));
         System.out.println(with);//2019-08-1

         //firstDayOfNextYear  明年的第一天
         System.out.println(LocalDate.now().with((temporal -> temporal.with(TemporalAdjusters.firstDayOfNextYear()))));//2020-01-01

         /**
          * nextOrSame/previousOrSame 创建一个新的日期,* 并将其值设定为日期调整后或者调整前,第一个符合指定星 期几要求的日期,如果该日期已经符合要求,直接返回该对象
          */
         // 今天是 2019-08-25 周日 下一个周一 返回 2019-08-26
         System.out.println(LocalDate.now().with((temporal -> temporal.with(TemporalAdjusters.nextOrSame(DayOfWeek.MONDAY)))));//2020-01-01
         // 返回下一个第一个满足的指定日期 也就是 周四  第一个是 2019-08-29  第二个是 2019-09-05  但是返回一个满足的。System.out.println(LocalDate.now().with(TemporalAdjusters.next(DayOfWeek.THURSDAY)));//2019-08-29

java.util.Date 与 LocalDate、LocalTime、LocalDateTime 转换


         Date date1 = new Date();
         System.out.println("current date:" + date1);
         ZonedDateTime zonedDateTime = date1.toInstant().atZone(ZoneId.systemDefault());
         //Date -> LocalDate
         LocalDate localDate31 = zonedDateTime.toLocalDate();
         System.out.println(localDate31);//2019-08-24

         //Date -> LocalDate
         ZonedDateTime zonedDateTime3 = date1.toInstant().atZone(ZoneId.of("Asia/Shanghai"));
         LocalDate localDate32 = zonedDateTime3.toLocalDate();
         System.out.println(localDate32);//2019-08-24

         //Date -> LocalDateTime
         LocalDateTime localDateTime1 = zonedDateTime.toLocalDateTime();
         //Date -> LocalDateTime 另一种方式
         LocalDateTime localDateTime2 = LocalDateTime.ofInstant(date1.toInstant(), ZoneId.systemDefault());


         //Date -> LocalTime
         LocalTime time1 = zonedDateTime.toLocalTime();

        //Calendar --> Instant
         Calendar.getInstance().toInstant();
jdk 8 中 Date 类中引入了 2 个方法,from 和 toInstant
         //LocalDateTime-> Date 方法 
         LocalDateTime localDateTime4 = LocalDateTime.now();
         System.out.println("localDateTime:" + localDateTime4);//2019-08-24T23:44:23.274

         //LocalDateTime-> Date 方法
         Date from2 = Date.from(localDateTime4.toInstant(ZoneOffset.UTC));
         Instant instant5 = from2.toInstant();
         System.out.println(from2);//Sun Aug 25 07:44:23 CST 2019
         System.out.println(instant5);//2019-08-24T23:44:23.274Z



         //// LocalDate -> Date
         LocalDate localDate3 = LocalDate.now();

         // 先把  LocalDate -> LocalDateTime
         LocalDateTime localDateTime3 = localDate3.atStartOfDay();
         // 再把 LocalDateTime -> Date
         Date from3 = Date.from(localDateTime3.toInstant(ZoneOffset.UTC));
         System.out.println(from3);
退出移动版