• 《Java8实战》读书笔记11:Java8中新的日期、时间API


    《Java8实战》读书笔记11:Java8中新的日期、时间API

    第 12 章 新的日期和时间API

    旧时间日期 API 表

    类名介绍
    java.util.Date1. 这个类无法表示日期,只能以毫秒的精度表示时间。
    2. 年份的起始选择是1900年,月份的起始从0开始。2014年3月18日 = Date date = new Date(114, 2, 18)
    3. 不支持时区,但 toString() 结果确默认显示时区信息。
    4. 可以变的。
    java.util.Calendar1. 月份依旧是从 0 开始计算。
    2. 可以变的。
    java.text.DateFormat不是线程安全的。

    Java8 时间日期 API 表

    这些新类都位于 java.time 包下。提供了统一风格的 API。
    下表所有类都实现了 Temporal 接口。
    如:获取年、月、日、周、时、分、秒等方法。

    接口介绍
    java.time.temporal接口。定义了如何读取和操纵为时间建模的对象的值。
    java.time.temporal.TemporalField接口。它定义了如何访问temporal对象某个字段的值。
    java.time.chrono.ChronoLocalDate用于高级全球化用例的任意时间表中没有时间或时区的日期。API的设计鼓励使用LocalDate而不是此接口,即使在应用程序需要处理多个日历系统的情况下也是如此。
    介绍
    java.time.LocalDate日期对象
    java.time.LocalTime时间对象
    java.time.LocalDateTimeLocalDateLocalTime 的合体。它表示日期和时间不带时区。可以直接创建,也可通过合并日期和时间来创建。
    ZonedDateTimeLocalDateLocalTime时区的合体
    java.time.Instant便于机器处理,从计算机的角度,对时间建模。是一个持续时间段上某个点。以 Unix元年(UTC时区1970年1月1日午夜时分)开始所经历的秒数。
    1. 可用于在应用程序中记录事件时间戳。
    java.time.Duration两个时间 Temporal 对象:AB之间持续的时长
    1. LocalDateTimeInstant 是为不同的目的而设计的,无法将二者混用计算时长
    2. 本类主要用于以纳秒衡量时间的长短,between方法不支持LocalDate做参数,因为它不带时间
    java.time.Period此类用于计算年、月、日之间持续的时长
    java.time.temporal.ChronoField此枚举实现了 TemporalField 接口,所以你可以很方便地使用 get 方法得到枚举元素的值。
    java.time.format.DateTimeFormatter用于打印和解析日期时间对象的格式化程序。
    ZoneOffset
    ZoneId

    12.1 LocalDate、LocalTime、Instant、Duration 以及 Period

    12.1.1 使用 LocalDate 和 LocalTime

    代码清单12-1 创建一个LocalDate对象并读取其值

    LocalDate date = LocalDate.of(2014, 3, 18); 
    int year = date.getYear(); 
    Month month = date.getMonth();
    int day = date.getDayOfMonth(); 
    DayOfWeek dow = date.getDayOfWeek(); 
    int len = date.lengthOfMonth();
    boolean leap = date.isLeapYear();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    使用工厂方法从系统时钟中获取当前的日期

    LocalDate today = LocalDate.now();
    
    • 1

    代码清单12-2 使用TemporalField读取LocalDate的值

    2022年07月04日

    int year = date.get(ChronoField.YEAR); 
    int month = date.get(ChronoField.MONTH_OF_YEAR); 
    int day = date.get(ChronoField.DAY_OF_MONTH);
    
    • 1
    • 2
    • 3

    代码清单12-3 创建LocalTime并读取其值

    LocalTime time = LocalTime.of(13, 45, 20); 
    int hour = time.getHour(); 
    int minute = time.getMinute(); 
    int second = time.getSecond();
    
    • 1
    • 2
    • 3
    • 4

    LocalDateLocalTime 都可以通过静态方法 parse 解析代表它们的字符串创建。

    LocalDate date = LocalDate.parse("2022-07-04"); 
    LocalTime time = LocalTime.parse("20:53:12");
    
    • 1
    • 2

    12.1.2 合并日期和时间

    代码清单12-4 直接创建LocalDateTime对象,或者通过合并日期和时间的方式创建

    // 2014-03-18T13:45:20 
    LocalDateTime dt1 = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45, 20); 
    LocalDateTime dt2 = LocalDateTime.of(date, time); 
    LocalDateTime dt3 = date.atTime(13, 45, 20); 
    LocalDateTime dt4 = date.atTime(time); 
    LocalDateTime dt5 = time.atDate(date);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    LocalDateTime中 提取 LocalDate 或者 LocalTime 组件:

    LocalDate date1 = dt1.toLocalDate(); 
    LocalTime time1 = dt1.toLocalTime();
    
    • 1
    • 2

    12.1.3 机器的日期和时间格式

    使用 纳秒 创建实例。以下都是:3秒之后。

    Instant.ofEpochSecond(3);		// 3秒之后
    Instant.ofEpochSecond(3, 0);	// 3秒之后 + 0纳秒
    Instant.ofEpochSecond(2, 1_000_000_000); // 2秒之后 + 10亿纳秒(1秒)
    Instant.ofEpochSecond(4, -1_000_000_000); // 4秒之后 - 10亿纳秒(1秒)
    
    • 1
    • 2
    • 3
    • 4

    12.1.4 定义 Duration 或 Period

    代码清单12-5 创建Duration和Period对象

    分别用于表示时间日期之间的时长

    Duration threeMinutes = Duration.ofMinutes(3); 
    Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES); 
    
    Period tenDays = Period.ofDays(10); 
    Period threeWeeks = Period.ofWeeks(3); 
    Period twoYearsSixMonthsOneDay = Period.of(2, 6, 1);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    表12-1 日期-时间类中表示时间间隔的通用方法

    Duration类和Period类共享了很多相似的方法,参见表12-1所示。

    方法名是否是静态方法方法描述
    between创建两个时间点之间的
    from由一个临时时间点创建
    of由它的组成部分创建
    parse由字符串创建
    addTo创建该
    get读取该
    isNegative检查该
    isZero检查该
    minus通过减去一定的时间创建该
    multipliedBy
    negated以忽略某个时长的方式创建该
    plus以增加某个指定的时长的方式创建该 interval 的副本
    subtractFrom从指定的 temporal 对象中减去该 interval

    12.2 操纵、解析和格式化日期

    代码清单12-6 以比较直观的方式操纵LocalDate的属性

    LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
    LocalDate date2 = date1.withYear(2011); // 2011-03-18
    LocalDate date3 = date2.withDayOfMonth(25); // 2011-03-25
    LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 9); // 2011-09-25
    
    • 1
    • 2
    • 3
    • 4

    代码清单12-7 以相对方式修改LocalDate对象的属性

    LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
    LocalDate date2 = date1.plusWeeks(1);  // 2014-03-25
    LocalDate date3 = date2.minusYears(3);  // 2011-03-25
    LocalDate date4 = date3.plus(6, ChronoUnit.MONTHS); // 2011-09-25
    
    • 1
    • 2
    • 3
    • 4

    表12-2 表示时间点的日期时间类的通用方法

    大概你已经猜到,像LocalDate、LocalTime、LocalDateTime以及Instant这样表示时
    间点的日期时间类提供了大量通用的方法,表12-2对这些通用的方法进行了总结。

    方法名是否是静态方法描述
    from依据传入的 Temporal对象创建对象实例
    now依据系统时钟创建 Temporal 对象
    ofTemporal对象的某个部分创建该对象的实例
    parse由字符串创建 Temporal 对象的实例
    atOffsetTemporal 对象和某个时区偏移相结合
    atZoneTemporal 对象和某个时区相结合
    format使用某个指定的格式器将 Temporal 对象转换为字符串(Instant类不提供该方法)
    get读取 Temporal对象的某一部分的值
    minus创建 Temporal 对象的一个副本,通过将当前 Temporal 对象的值减去一定的时长创建该副本
    plus创建 Temporal 对象的一个副本,通过将当前 Temporal 对象的值加上一定的时长创建该副本
    with以该 Temporal 对象为模板,对某些状态进行修改创建该对象的副本

    12.2.1 使用 TemporalAdjuster

    代码清单12-8 使用预定义的TemporalAdjuster

    import static java.time.temporal.TemporalAdjusters.*; 
    LocalDate date1 = LocalDate.of(2014, 3, 18); // 2014-03-18
    LocalDate date2 = date1.with(nextOrSame(DayOfWeek.SUNDAY)); // 2014-03-23
    LocalDate date3 = date2.with(lastDayOfMonth()); // 2014-03-31
    
    • 1
    • 2
    • 3
    • 4

    表12-3 TemporalAdjuster类中的工厂方法

    表12-3提供了TemporalAdjuster中包含的工厂方法列表。

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

    代码清单12-9 TemporalAdjuster接口

    TemporalAdjuster 是一个 函数式接口

    @FunctionalInterface 
    public interface TemporalAdjuster { 
     Temporal adjustInto(Temporal temporal); 
    }
    
    • 1
    • 2
    • 3
    • 4

    12.2.2 打印输出及解析日期时间对象

    java.time.format 这个包下都是时间格式化相关的内容 。最重要的比如:DateTimeFormatter

    • 使用了两个不同的格式器生成了字符串
    LocalDate date = LocalDate.of(2014, 3, 18);
    String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE); // 20140318
    String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE); // 2014-03-18
    
    • 1
    • 2
    • 3
    • 以使用工厂方法parse达到重创该日期对象
      和老的java.util.DateFormat相比较,所有的DateTimeFormatter实例都是线程安全的。
    LocalDate date1 = LocalDate.parse("20140318", DateTimeFormatter.BASIC_ISO_DATE); 
    LocalDate date2 = LocalDate.parse("2014-03-18", DateTimeFormatter.ISO_LOCAL_DATE);
    
    • 1
    • 2

    代码清单12-10 按照某个模式创建DateTimeFormatter

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
    LocalDate date1 = LocalDate.of(2014, 3, 18); 
    String formattedDate = date1.format(formatter); 
    LocalDate date2 = LocalDate.parse(formattedDate, formatter);
    
    • 1
    • 2
    • 3
    • 4

    代码清单12-11 创建一个本地化的DateTimeFormatter

    DateTimeFormatter italianFormatter = DateTimeFormatter.ofPattern("d. MMMM yyyy", Locale.ITALIAN); 
    LocalDate date1 = LocalDate.of(2014, 3, 18); 
    String formattedDate = date.format(italianFormatter); // 18. marzo 2014 
    LocalDate date2 = LocalDate.parse(formattedDate, italianFormatter);
    
    • 1
    • 2
    • 3
    • 4

    代码清单12-12 构造一个DateTimeFormatter

    DateTimeFormatter italianFormatter = new DateTimeFormatterBuilder() 
     .appendText(ChronoField.DAY_OF_MONTH) 
     .appendLiteral(". ") 
     .appendText(ChronoField.MONTH_OF_YEAR) 
     .appendLiteral(" ") 
     .appendText(ChronoField.YEAR) 
     .parseCaseInsensitive() 
     .toFormatter(Locale.ITALIAN);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    12.3 处理不同的时区和历法

    代码清单12-13 为时间点添加时区信息

    LocalDate date = LocalDate.of(2014, Month.MARCH, 18); 
    ZonedDateTime zdt1 = date.atStartOfDay(romeZone); 
    LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); 
    ZonedDateTime zdt2 = dateTime.atZone(romeZone); 
    Instant instant = Instant.now(); 
    ZonedDateTime zdt3 = instant.atZone(romeZone);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    在这里插入图片描述
    通过ZoneId,你还可以将LocalDateTime转换为Instant:

    LocalDateTime dateTime = LocalDateTime.of(2014, Month.MARCH, 18, 13, 45); 
    Instant instantFromDateTime = dateTime.toInstant(romeZone); 
    
    • 1
    • 2

    你也可以通过反向的方式得到LocalDateTime对象:

    Instant instant = Instant.now(); 
    LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);
    
    • 1
    • 2

    12.3.1 利用和 UTC/格林尼治时间的固定偏差计算时区

    “纽约落后于伦敦5小时”。

    ZoneOffset newYorkOffset = ZoneOffset.of("-05:00");
    
    • 1

    12.3.2 使用别的日历系统

    略。。。

    12.4 小结

    • 这一章中,你应该掌握下面这些内容。
    1. Java 8之前版的java.util.Date类以及其他用于建模日期时间的类有很多不一致及设计上的缺陷,包括易变性以及糟糕的偏移值、默认值和命名。
    2. 新版的日期和时间API中,日期-时间对象是不可变的。
    3. 新的API提供了两种不同的时间表示方式,有效地区分了运行时机器的不同需求。
    4. 你可以用绝对或者相对的方式操纵日期和时间,操作的结果总是返回一个新的实例老的日期时间对象不会发生变化
    5. TemporalAdjuster让你能够用更精细的方式操纵日期,不再局限于一次只能改变它的一个值,并且你还可按照需求定义自己的日期转换器。
    6. 你现在可以按照特定的格式需求,定义自己的格式器,打印输出或者解析日期时间对象。这些格式器可以通过模板创建,也可以自己编程创建,并且它们都是线程安全的。
    7. 你可以用相对于某个地区/位置的方式,或者以与UTC/格林尼治时间的绝对偏差的方式表示时区,并将其应用到日期时间对象上,对其进行本地化。
    8. 你现在可以使用不同于ISO-8601标准系统的其他日历系统了。

    参考资料

    笑虾 :Java 学习笔记 - Java8的日期时间 LocalDateTime
    笑虾 :Java 学习笔记 - 时间日期常用案列

  • 相关阅读:
    基于springboot+vue的爱心助农网站(前后端分离)
    高性能网络通信框架--Mercury
    行为型模式-中介者模式
    推荐 系统
    论文:Bottom-Up Constituency Parsing+document error analysis
    Go 小知识之 Go 中如何使用 set
    MySQL索引失效原理是什么?
    定时任务-启动服务立即执行一次,再按照cron表达式等待下一次执行
    基于springboot实现贸易行业crm系统项目【项目源码+论文说明】
    Pytorch总结九之深度学习计算(2)自定义层、读取和存储、GPU计算
  • 原文地址:https://blog.csdn.net/jx520/article/details/125607895