Java 8新特性之新的日期和时间API(4)

处理日期和时间对象时,格式化以及解析日期-时间对象是另一个非常重要的功能。新的java.time.format包就是为了这个目的而设计的。这个包中最重要的类是DateTimeFormatter,创建格式器最简单的方式是通过他的静态工厂方法及常量。

String s1 = next.format(DateTimeFormatter.BASIC_ISO_DATE); //20180824
        String s2 = next.format(DateTimeFormatter.ISO_LOCAL_DATE); //2018-08-24

除了解析为字符串外,还可以通过解析代表日期或时间的字符串重新创建该日期对象。

LocalDate date1 = LocalDate.parse("20180901",DateTimeFormatter.BASIC_ISO_DATE);
        LocalDate date2 = LocalDate.parse("2018-09-02",DateTimeFormatter.ISO_LOCAL_DATE);

与老的java.util.DateFormat想比较,所有的DateTimeFormatter实例都是线程安全的。DateTimeFormatter类还支持一个静态工厂方法,它按照某个特定的模式创建格式器。

DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
        LocalDate now = LocalDate.now();
        String formatterDate = now.format(formatter);
        LocalDate nowparse = LocalDate.parse(formatterDate,formatter);

ofPattern可以按照指定的格式进行解析成字符串,然后又调用了parse方法的重载 将该格式的字符串转换成了 LocalDate对象。

ofPattern也提供了重载版本,使用它可以创建某个Locale的格式器:

DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy年MMMMd号", Locale.CHINA);
        LocalDate chinaDate = LocalDate.parse("2018-08-21");
        String formatterDate2 = chinaDate.format(formatter2); //2018年八月21号
        LocalDate chinaDate2 = LocalDate.parse(formatterDate2,formatter2);

DateFormatterBuilder类还提供了更复杂的格式器和更强大的解析功能:

DateTimeFormatter chinaFormatter = new DateTimeFormatterBuilder().appendText(ChronoField.YEAR)
                .appendLiteral("年")
                .appendText(ChronoField.MONTH_OF_YEAR)
                .appendText(ChronoField.DAY_OF_MONTH)
                .appendLiteral("号")
                .parseCaseInsensitive().toFormatter(Locale.CHINA);

处理不同的时区和历法

之前所看到的日期和时间种类都不包含时区信息。时区的处理是新版日期和时间API新增加的重要功能,新的 java.time.ZoneId 类是老版 java.util.TimeZone 的替代品。

时区是按照一定的规则将区域划分成的标准时间相同的区间。在ZoneRules这个类中包含了40个这样的实例。你可以使用ZoneId的getRules()得到指定时区的规则。每个特定的ZoneId对象都由一个地区标识:

ZoneId romeZone = ZoneId.of("Europe/Rome"); //格式 欧洲/罗马

地区ID都为 “{区域}/{城市}”的格式,这些地区集合的设定都由英特网编号分配机构(IANA)的时区数据库提供。你可以通过java 8的新方法toZoneId将一个老的时区对象转换为ZoneId

ZoneId zoneId = TimeZone.getDefault().toZoneId();

一旦得到一个ZoneId对象,就可以将它与LocalDate、LocalDateTIme或者是Instant对象整合起来,构造为一个ZonedDateTime实例,它代表了相对于指定时区的时间点,

LocalDate date = LocalDate.of(2018,8,22);
        ZonedDateTime zdt1 = date.atStartOfDay(romeZone);

LocalDateTime dateTime = LocalDateTime.of(2018,8,23,13,48,00);
        ZonedDateTime zdt2 = dateTime.atZone(romeZone);

Instant instant = Instant.now();
        ZonedDateTime zdt3 = instant.atZone(romeZone);

ZonedDateTime = LocalDateTime(LocalDate + LocalTime) + ZoneId

通过ZoneId,你还可以将LocalDateTime转换为Instant

LocalDateTime dateTime = LocalDateTime.of(2018,8,23,13,48,00);
        Instant instantFromDateTime = dateTime.toInstant(romeZone);

Instant instant1 = Instant.now();
        LocalDateTime timeFromInstant = LocalDateTime.ofInstant(romeZone);

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

另一种比较常用的表达时区的方式就是利用当前时区和 UTC/格林尼治 的固定偏差,比如,纽约落后伦敦5小时。这种情况下,你可以使用ZoneOffset类,它是ZoneId的一个子类,表示的是当前时间和伦敦格林尼治子午时间的差异:

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

这种方式不推荐使用,因为 -05:00 的偏差实际上是对应的美国东部标准时间,并未考虑任何日光时的影响。

LocalDateTime dateTime1 = LocalDateTime.now();
        OffsetDateTime dateTimeInNewYork1 = OffsetDateTime.of(dateTime1,newYorkOffset);

它使用ISO-8601的历法系统,以相对于UTC时间的偏差方式表示日期时间。

使用别的日历系统

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/c7ea4d849be6cbb0ba2bf82b5110a5be.html