JavaRush /Java 博客 /Random-ZH /Java 中终于提供了一个直观、强大的处理时间和日期的库(第 2 部分)。
theGrass
第 24 级
Саратов

Java 中终于提供了一个直观、强大的处理时间和日期的库(第 2 部分)。

已在 Random-ZH 群组中发布
一天的时间
    那么让我们继续吧。date 之后的下一个实体是一天中的时间,由LocalTime类表示。一个典型的例子是表示商店的营业时间,例如 7:00 到 23:00。全国各地的商店都在这个时间营业,但实际时间会根据时区而有所不同。     LocalTime是一个仅存储时间的值类,没有关联的日期或时区。添加或减少时间段时,会在午夜截止。即20:00加6个小时就是2:00。使用LocalTime与LocalDate类似: LocalTime time = LocalTime.of(20, 30); int hour = date.getHour(); // 20 int minute = date.getMinute(); // 30 time = time.withSecond(6); // 20:30:06 time = time.plusMinutes(3); // 20:33:06     修饰符可以与LocalTime一起使用,但时间操作通常不会复杂到需要修饰符。
合并日期和时间
    我们要查看的下一个类是 LocalDateTime该值类是LocalDateLocalTime的组合。它代表日期和时间,没有时区。      LocalDateTime可以直接创建,也可以通过组合日期和时间来创建: LocalDateTime dt1 = LocalDateTime.of(2014, Month.JUNE, 10, 20, 30); LocalDateTime dt2 = LocalDateTime.of(date, time); LocalDateTime dt3 = date.atTime(20, 30); LocalDateTime dt4 = date.atTime(time);     第三个和第四个选项使用 atTime()方法,该方法提供了组合日期和时间的灵活方式。大多数日期和时间系统类都有“at”方法,可以在将对象与另一个对象组合以创建更复杂的对象时使用这些方法。 LocalDateTime类的其他方法与 LocalDateLocalTime的方法类似。 类似的方法命名模式使API更易于学习。下表列出了所有涉及的方法前缀: Java 中终于提供了一个直观、强大的处理时间和日期的库(第 2 部分)。 - 1
立即的
    当我们处理日期和时间时,我们通常会处理年、月、日、小时、分钟、秒。然而,这只是一种可以称为“人类”的时间模型。常用的第二种模型是“机器”或“连续”时间。在该模型中,时间轴上的一点由一个大数字表示。 这种方法简化了计算算法,用于存储Unix操作系统中的时间,其中时间用自 1970 年 1 月 1 日以来经过的秒数表示。同样,在 Java中,时间存储为自 1970 年 1 月 1 日以来经过的毫秒数。 java.time API中时间计算的机器方法由 Instant值类提供。它提供了在时间轴上表示点的能力,而无需所有附带信息(例如时区)。事实上,此类包含自 1970 年 1 月 1 日午夜以来经过的纳秒数。 Instant start = Instant.now(); // произведем вычисления Instant end = Instant.now(); assert end.isAfter(start); //машина времени не сработала     通常,当您需要存储某个事件发生的时间但不关心事件发生的时区时, Instant类用于存储和比较时间点。在大多数情况下,我们不能用 Instant类做什么比我们可以用它做什么更有趣。例如,以下代码行将引发异常: instant.get(ChronoField.MONTH_OF_YEAR); instant.plus(6, ChronoUnit.YEARS);     发生异常是因为 即时对象仅存储纳秒数,并且不提供使用对人类更有用的时间单位的能力。要使用其他测量单位,您必须至少指定一个时区。
时区
    时区的原理是在英国发展起来的,当时铁路的发明和其他通讯方式的改进使人们能够旅行足够远的距离,使太阳时的差异变得明显。直到此时,每个村庄和城市都按照自己的时间生活,而时间通常是通过日晷来测量的。这张图展示了由此带来的困难的一个例子——时钟上的红针显示格林威治时间,黑针显示当地时间,相差10分钟:时区系统发展起来,取代了当地太阳时 Java 中终于提供了一个直观、强大的处理时间和日期的库(第 2 部分)。 - 2     。但关键事实是,时区是由政客创建的,并且经常被用来展示对某个地区的政治控制。与任何政策一样,与时区相关的规则常常不符合逻辑。而且,这些规则可能会改变,而且经常会在没有任何警告的情况下改变。时区规则由发布 IANA时区数据库的国际组织编制。它包含地球每个区域的标识符及其时区变化的历史。标识符看起来像 “Europe/London”“America/New_York”在java.time API发布之前, TimeZone类用于表示时区。现在改用 ZoneId。它们之间有两个关键区别。首先, ZoneId是不可变的,这使得可以将此类的对象存储在静态变量中。其次,规则本身存储在 ZoneRules类中,而不是存储在 ZoneId本身中,要获取它们,您需要调用 ZoneId类对象上的 getRules()方法。 所有时区的一个共同特征是与UTC/格林威治的固定偏移量。大多数情况下,您在谈论不同城市之间的时差时会使用此词,例如“纽约比伦敦晚 5 小时”。 ZoneOffset类是 ZoneId的后代,表示与穿过伦敦格林威治的本初子午线的时差。从开发人员的角度来看,如果不必处理时区及其复杂性,那就太好了。 java.time API允许您尽可能地执行此操作。尽可能使用 LocalDate、LocalTime、LocalDateTimeInstant类。如果您不能没有时区,请使用 ZonedDateTime类。 分区日期时间 允许您将日期和时间从我们在日历和手表上看到的人类测量单位转换为机器单位。因此,您可以从 Local类或 Instant 类创建 ZonedTimeDate:     时区最令人不快的功能之一是所谓的夏令时。随着夏令时在格林威治之间切换,您与格林威治的时区差每年变化两次(或多次),通常在春季增加,在秋季减少。当这种情况发生时,我们必须更换家里所有的时钟。在 java.time类中,偏移数据表示为 “偏移变换”。在春季,这会导致时间“间隙”,此时某些时间值是不可能的,而在秋季,相反,某些时间值会出现两次。 所有这些都由ZonedDateTime类通过其工厂方法和转换器方法支持。例如,添加一天会添加一个逻辑日,如果我们切换到夏令时或返回夏令时,则可以用多于或少于 24 小时来表示。 同样, atStartOfDay()方法之所以如此命名,是因为我们无法保证这一天恰好在午夜开始——我们必须考虑切换到夏令时时的时间间隔。关于夏令时的最后一个提示。如果您想证明您已考虑从夏季到冬季过渡期间的时间重叠(当相同的时间值出现两次时),您可以使用专为此类情况设计的两种特殊方法之一: 这些方法将返回较早或较晚的时间     value ,如果对象在从夏季到冬季的过渡期间陷入重叠。在所有其他情况下,返回值将是相同的。 ZoneId zone = ZoneId.of("Europe/Paris"); LocalDate date = LocalDate.of(2014, Month.JUNE, 10); ZonedDateTime zdt1 = date.atStartOfDay(zone); Instant instant = Instant.now(); ZonedDateTime zdt2 = instant.atZone(zone); zdt = zdt.withEarlierOffsetAtOverlap(); zdt = zdt.withLaterOffsetAtOverlap();
时间间隔
    我们之前讨论的所有类都以时间线上的点的形式工作。需要两个附加值类来表示时间间隔。 Duration类表示时间长度,以秒和纳秒为单位。例如,“23.6 秒”。 period类表示以年、月和日为单位的一段时间。例如 - “3 年 2 个月零 6 天。” 可以从日期或时间中添加或减去这些间隔: Period sixMonths = Period.ofMonths(6); LocalDate date = LocalDate.now(); LocalDate future = date.plus(sixMonths);
格式化和解析
    整个包旨在格式化和显示日期和时间 - java.time.format。该包围绕 DateTimeFormatter类及其 DateTimeFormatterBuilder工厂。创建格式化程序的最常见方法是通过 DateTimeFormatter中的静态方法和常量,包括:
  • ISO 中描述的常见格式常量,例如 ISO_LOCAL_DATE。
  • 由字母标识的模式,例如 ofPattern("dd/MM/uuuu")。
  • 本地化样式,例如 ofLocalizedDate(FormatStyle.MEDIUM)。
    创建格式化程序后,通常通过将其传递给适当的日期类方法来使用它: DateTimeFormatter f = DateTimeFormatter.ofPattern("dd/MM/uuuu"); LocalDate date = LocalDate.parse("24/06/2014", f); String str = date.format(f);     这样,负责格式化日期输出的代码就被隔离到一个单独的类中。如果需要单独指定日期格式化的区域设置,请使用 withLocale(Locale)格式化程序方法。负责日历、时区和小数输入/输出的类具有类似的方法。如果您需要更多微调选项,请参阅 DateTimeFormatterBuilder类的文档,它允许您逐步创建复杂的格式化程序。它还允许您设置不区分大小写的文本解析、忽略一些解析错误、设置偏移量和可选元素。
底线
     java.time API是 Java SE 8中处理日期和时间的新综合模型。它将 Joda-Time的思想和实现提升到了一个新的水平,并最终允许开发人员避免使用 java.util.DateCalendar。现在处理日期和时间会很有趣!      来源文章
评论
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION