Java8新特性 | 新的日期时间API

本文源码:Gitee·点这里

Java 8通过发布新的JSR 310: Date and Time API来进一步加强对日期与时间的处理。java.time是基于国际化标准日历系统(International Organization for Standardization)ISO-8601的,同时java.time.chrono支持对全球日历系统的扩展。

新的java.time涵盖了所有处理日期、时间、日期-时间、时区、时刻(instants)、时长(during)与时钟(clock)的操作。所有的类都是不可变的,线程安全的。

该套API的方法,通过使用一致的方法前缀来管理:

  • of - 静态工厂方法,用于根据属性值创建实例
  • parse - 静态工厂方法集中于解析
  • get - 获取get的值
  • is - 检查是否正确
  • with - 设定某个属性的值,不改变原实例值,而是创建一个新的实例
  • plus - 向对象添加值
  • minus - 从对象中减去值
  • to - 将此对象转换为另一种类型
  • at - 将此对象与另一个对象组合,如date.atTime(time)

LocalDate (日期)

LocalDate是一个不可变的日期对象,通常被视为年月日。 也可以访问其他日期字段,例如日期和星期。

该类是对日期的描述,不能代表时间线上的某一时刻,而且没有时间、偏移和时区。该类比较适合用于生日。通过下面的示例代码来了解其方法的使用。

示例代码:

public class LocalDateDemo {

    public static void main(String[] args) {
        // 从默认时区的系统时钟获取当前日期
        LocalDate localDate1 = LocalDate.now();
        // 将此日期输出为 String ,如 2007-12-03 。
        System.out.println("01: " + localDate1);

        // 从一年,一个月和一天获得一个 LocalDate的实例
        LocalDate localDate2 = LocalDate.of(2020, 12, 1);
        System.out.println("02: " + localDate2);

        // 从一年中的第n天获取LocalDate实例
        LocalDate localDate3 = LocalDate.ofYearDay(2020, 45);
        System.out.println("03: " + localDate3);

        // 从一个文本字符串(如 2007-12-03)获取一个 LocalDate的实例,使用默认 DateTimeFormatter.ISO_LOCAL_DATE 格式
        LocalDate localDate4 = LocalDate.parse("2020-12-02");
        System.out.println("04: " + localDate4);
        // 使用特定格式化,从文本字符串获取 LocalDate的实例。
        LocalDate localDate5 = LocalDate.parse("2020/10/03", DateTimeFormatter.ofPattern("yyyy/MM/dd"));
        System.out.println("05: " + localDate5);

        // 获取年
        System.out.println("06: " + localDate5.getYear());
        // 获取月
        System.out.println("07: " + localDate5.getMonthValue());
        // 获取日
        System.out.println("08: " + localDate5.getDayOfMonth());

        // 是否在指定日期之后
        System.out.println("09: " + localDate5.isAfter(localDate4));
        // 是否在指定日期之前
        System.out.println("10: " + localDate5.isBefore(localDate4));
        // 是否与指定日期相等
        System.out.println("11: " + localDate5.isEqual(localDate4));

        // 更改年份,并返回新的实例
        System.out.println("12: " + localDate5.withYear(2019));
        // 更改月份,并返回新的实例
        System.out.println("13: " + localDate5.withMonth(10));
        // 更改日期,并返回新的实例
        System.out.println("14: " + localDate5.withDayOfMonth(9));

        // 年份增加指定值,并返回新的实例
        System.out.println("15: " + localDate5.plusYears(1));
        // 月份增加指定值,并返回新的实例
        System.out.println("16: " + localDate5.plusMonths(1));
        // 日期增加指定值,并返回新的实例
        System.out.println("17: " + localDate5.plusDays(1));

        // 年份减去指定值,并返回新的实例
        System.out.println("18: " + localDate5.minusYears(1));
        // 月份减去指定值,并返回新的实例
        System.out.println("19: " + localDate5.minusMonths(1));
        // 日期减去指定值,并返回新的实例
        System.out.println("20: " + localDate5.minusDays(1));

        // 按照指定格式返回一个字符串
        System.out.println("21: " + localDate5.format(DateTimeFormatter.ofPattern("yyyy/MM/dd")));

        // 添加时间的小时、分钟、秒,获取一个 LocalDateTime 实例
        System.out.println("22: " + localDate5.atTime(10, 11, 12));
        // 添加一个 LocalTime 获取一个 LocalDateTime 实例
        System.out.println("23: " + localDate5.atTime(LocalTime.now()));
    }
}

输出结果:

01: 2020-11-11
02: 2020-12-01
03: 2020-02-14
04: 2020-12-02
05: 2020-10-03
06: 2020
07: 10
08: 3
09: false
10: true
11: false
12: 2019-10-03
13: 2020-10-03
14: 2020-10-09
15: 2021-10-03
16: 2020-11-03
17: 2020-10-04
18: 2019-10-03
19: 2020-09-03
20: 2020-10-02
21: 2020/10/03
22: 2020-10-03T10:11:12
23: 2020-10-03T10:05:39.715

LocalTime (时间)

LocalTime是一个不可变的时间对象,通常被看作时-分-秒,精度为纳秒,例如:13:45:30.123456789。

它不存储日期、时区、偏移,也不能表示时间线上的某一时刻。通过下面的示例代码来了解其方法的使用。

示例代码:

public class LocalTimeDemo {

    public static void main(String[] args) {

        // 从默认时区的系统时钟获取当前时间
        LocalTime localTime1 = LocalTime.now();
        System.out.println("01: " + localTime1);

        // 通过时、分、秒创建一个 LocalTime 实例
        LocalTime localTime2 = LocalTime.of(10, 2, 15);
        System.out.println("02: " + localTime2);

        // 从一天中的第n秒获取 LocalTime 实例
        LocalTime localTime3 = LocalTime.ofSecondOfDay(100);
        System.out.println("03: " + localTime3);

        // 从一个文本字符串(如:10:15)获取一个 LocalTime 的实例,使用默认 DateTimeFormatter.ISO_LOCAL_TIME 格式
        LocalTime localTime4 = LocalTime.parse("10:01:12");
        System.out.println("04: " + localTime4);
        // 使用特定格式化,从文本字符串获取 LocalTime 的实例。
        LocalTime localTime5 = LocalTime.parse("11:02:13.111", DateTimeFormatter.ofPattern("HH:mm:ss.SSS"));
        System.out.println("05: " + localTime5);

        // 获取小时
        System.out.println("06: " + localTime5.getHour());
        // 获取分钟
        System.out.println("07: " + localTime5.getMinute());
        // 获取秒
        System.out.println("08: " + localTime5.getSecond());

        // 是否在指定时间之后
        System.out.println("09: " + localTime5.isAfter(localTime4));
        // 是否在指定时间之前
        System.out.println("10: " + localTime5.isBefore(localTime4));
        // 是否与指定时间相等
        System.out.println("11: " + localTime5.equals(localTime4));

        // 更改小时,并返回新的实例
        System.out.println("12: " + localTime5.withHour(12));
        // 更改分钟,并返回新的实例
        System.out.println("13: " + localTime5.withMinute(3));
        // 更改秒数,并返回新的实例
        System.out.println("14: " + localTime5.withSecond(14));

        // 小时增加指定值,并返回新的实例
        System.out.println("15: " + localTime5.plusHours(1));
        // 分钟增加指定值,并返回新的实例
        System.out.println("16: " + localTime5.plusMinutes(1));
        // 秒数增加指定值,并返回新的实例
        System.out.println("17: " + localTime5.plusSeconds(1));

        // 小时减去指定值,并返回新的实例
        System.out.println("18: " + localTime5.minusHours(1));
        // 分钟减去指定值,并返回新的实例
        System.out.println("19: " + localTime5.minusMinutes(1));
        // 秒数减去指定值,并返回新的实例
        System.out.println("20: " + localTime5.minusSeconds(1));

        // 按照指定格式返回一个字符串
        System.out.println("21: " + localTime5.format(DateTimeFormatter.ofPattern("HH:mm:ss")));
        System.out.println("22: " + localTime5.format(DateTimeFormatter.ofPattern("HH:mm:ss.SSS")));

        // 添加一个 LocalDate 获取一个 LocalDateTime 实例
        System.out.println("23: " + localTime5.atDate(LocalDate.now()));

    }
}

输出结果:

01: 10:11:47.621
02: 10:02:15
03: 00:01:40
04: 10:01:12
05: 11:02:13.111
06: 11
07: 2
08: 13
09: true
10: false
11: false
12: 12:02:13.111
13: 11:03:13.111
14: 11:02:14.111
15: 12:02:13.111
16: 11:03:13.111
17: 11:02:14.111
18: 10:02:13.111
19: 11:01:13.111
20: 11:02:12.111
21: 11:02:13
22: 11:02:13.111
23: 2020-11-11T11:02:13.111

LocalDateTime (日期-时间)

LocalDateTime是一个不可变的日期-时间对象,通常被视为年-月-日-时-分-秒,也可以访问其他日期和时间字段,例如日期,星期。时间精度为纳秒,例如:2007年10月2日13:45:30.123456789。
通过下面的示例代码来了解其方法的使用。

示例代码:

public class LocalDateTimeDemo {

    public static void main(String[] args) {

        // 从默认时区的系统时钟获取当前日期-时间
        LocalDateTime localDateTime1 = LocalDateTime.now();
        System.out.println("01: " + localDateTime1);

        // 通过年、月、日、时、分、秒获得 LocalDateTime 的实例
        LocalDateTime localDateTime2 = LocalDateTime.of(2020, 12, 1, 10, 11, 12);
        System.out.println("02: " + localDateTime2);

        // 通过 LocalDate 和 LocalTime 获得 LocalDateTime 的实例
        LocalDateTime localDateTime3 = LocalDateTime.of(LocalDate.now(), LocalTime.now());
        System.out.println("03: " + localDateTime3);

        // 从一个文本字符串(如 2007-12-03T10:15:30)获取一个 LocalDateTime 的实例,使用默认 DateTimeFormatter.ISO_LOCAL_DATE_TIME 格式
        LocalDateTime localDateTime4 = LocalDateTime.parse("2020-12-01T10:11:12");
        System.out.println("04: " + localDateTime4);
        // 使用特定的格式化,从文本字符串获取 LocalDateTime的实例。
        LocalDateTime localDateTime5 = LocalDateTime.parse("2020-12-01 10:11:12", DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        System.out.println("05: " + localDateTime5);

        // 获取年
        System.out.println("06: " + localDateTime5.getYear());
        // 获取月
        System.out.println("07: " + localDateTime5.getMonthValue());
        // 获取日
        System.out.println("08: " + localDateTime5.getDayOfMonth());
        // 获取时
        System.out.println("09: " + localDateTime5.getHour());
        // 获取分
        System.out.println("10: " + localDateTime5.getMinute());
        // 获取秒
        System.out.println("11: " + localDateTime5.getSecond());

        // 是否在指定日期-时间之后
        System.out.println("12: " + localDateTime5.isAfter(localDateTime4));
        // 是否在指定日期-时间之前
        System.out.println("13: " + localDateTime5.isBefore(localDateTime4));
        // 是否与指定日期-时间相等
        System.out.println("14: " + localDateTime5.isEqual(localDateTime4));


        // 更改年份,并返回新的实例
        System.out.println("15: " + localDateTime5.withYear(2019));
        // 更改月份,并返回新的实例
        System.out.println("16: " + localDateTime5.withMonth(10));
        // 更改日期,并返回新的实例
        System.out.println("17: " + localDateTime5.withDayOfMonth(9));
        // 更改小时,并返回新的实例
        System.out.println("18: " + localDateTime5.withHour(12));
        // 更改分钟,并返回新的实例
        System.out.println("19: " + localDateTime5.withMinute(3));
        // 更改秒数,并返回新的实例
        System.out.println("20: " + localDateTime5.withSecond(14));

        // 年份增加指定值,并返回新的实例
        System.out.println("21: " + localDateTime5.plusYears(1));
        // 月份增加指定值,并返回新的实例
        System.out.println("22: " + localDateTime5.plusMonths(1));
        // 日期增加指定值,并返回新的实例
        System.out.println("23: " + localDateTime5.plusDays(1));
        // 小时增加指定值,并返回新的实例
        System.out.println("24: " + localDateTime5.plusHours(1));
        // 分钟增加指定值,并返回新的实例
        System.out.println("25: " + localDateTime5.plusMinutes(1));
        // 秒数增加指定值,并返回新的实例
        System.out.println("26: " + localDateTime5.plusSeconds(1));

        // 年份减去指定值,并返回新的实例
        System.out.println("27: " + localDateTime5.minusYears(1));
        // 月份减去指定值,并返回新的实例
        System.out.println("28: " + localDateTime5.minusMonths(1));
        // 日期减去指定值,并返回新的实例
        System.out.println("29: " + localDateTime5.minusDays(1));
        // 小时减去指定值,并返回新的实例
        System.out.println("30: " + localDateTime5.minusHours(1));
        // 分钟减去指定值,并返回新的实例
        System.out.println("31: " + localDateTime5.minusMinutes(1));
        // 秒数减去指定值,并返回新的实例
        System.out.println("32: " + localDateTime5.minusSeconds(1));

        // 按照指定格式返回一个字符串
        System.out.println("33: " + localDateTime5.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));

        // 获取 LocalDate 实例
        System.out.println("34: " + localDateTime5.toLocalDate());
        // 获取 LocalTime 实例
        System.out.println("35: " + localDateTime5.toLocalTime());

    }

}

输出结果:

01: 2020-11-11T10:13:04.496
02: 2020-12-01T10:11:12
03: 2020-11-11T10:13:04.496
04: 2020-12-01T10:11:12
05: 2020-12-01T10:11:12
06: 2020
07: 12
08: 1
09: 10
10: 11
11: 12
12: false
13: false
14: true
15: 2019-12-01T10:11:12
16: 2020-10-01T10:11:12
17: 2020-12-09T10:11:12
18: 2020-12-01T12:11:12
19: 2020-12-01T10:03:12
20: 2020-12-01T10:11:14
21: 2021-12-01T10:11:12
22: 2021-01-01T10:11:12
23: 2020-12-02T10:11:12
24: 2020-12-01T11:11:12
25: 2020-12-01T10:12:12
26: 2020-12-01T10:11:13
27: 2019-12-01T10:11:12
28: 2020-11-01T10:11:12
29: 2020-11-30T10:11:12
30: 2020-12-01T09:11:12
31: 2020-12-01T10:10:12
32: 2020-12-01T10:11:11
33: 2020-12-01 10:11:12
34: 2020-12-01
35: 10:11:12

Instant (时刻/时间戳)

该类表示在时间线上的时刻点。这比较适合在应用程序中记录事件的时间戳。
值得注意的是其时区默认使用的是UTC标准时区,若要在你当前时区使用,需要设置好时区。

示例代码:

public class InstantDemo {

    public static void main(String[] args) {

        // 从系统时钟获取当前时间戳,值得注意的是通过此方法获取的时间戳是基于UTC标准时区的
        Instant instant1 = Instant.now();
        System.out.println("01: " + instant1);

        // 可以通过设置时区,来获取指定时区的日期-时间
        ZonedDateTime zonedDateTime = instant1.atZone(ZoneId.systemDefault());
        System.out.println("01: " + zonedDateTime.toLocalDateTime());

        // 通过指定字符串转换为 Instant 实例
        Instant instant2 = Instant.parse("2020-11-05T11:22:33Z");
        System.out.println("03: " + instant2);

        // 是否在指定时间戳之后
        System.out.println("04: " + instant2.isAfter(instant1));
        // 是否在指定时间戳之前
        System.out.println("05: " + instant2.isBefore(instant1));

    }
}

输出结果:

01: 2020-11-11T02:23:03.870Z
01: 2020-11-11T10:23:03.870
03: 2020-11-05T11:22:33Z
04: false
05: true

Duration (时长)

基于时间的时间量,如:34.5秒。
该类你可能在SpringBoot配置中见到过,下面是一些示例:

  • "PT20.345S" -- parses as "20.345 seconds"
  • "PT15M" -- parses as "15 minutes" (where a minute is 60 seconds)
  • "PT10H" -- parses as "10 hours" (where an hour is 3600 seconds)
  • "P2D" -- parses as "2 days" (where a day is 24 hours or 86400 seconds)
  • "P2DT3H4M" -- parses as "2 days, 3 hours and 4 minutes"
  • "P-6H3M" -- parses as "-6 hours and +3 minutes"
  • "-P6H3M" -- parses as "-6 hours and -3 minutes"
  • "-P-6H+3M" -- parses as "+6 hours and -3 minutes"

示例代码:

public class DurationDemo {

    public static void main(String[] args) {

        // 根据天获取实例
        Duration duration1 = Duration.ofDays(1);
        System.out.println("01: " + duration1);
        // 根据小时获取实例
        Duration duration2 = Duration.ofHours(10);
        System.out.println("02: " + duration2);
        // 根据分钟获取实例
        Duration duration3 = Duration.ofMinutes(20);
        System.out.println("03: " + duration3);
        // 根据秒获取实例
        Duration duration4 = Duration.ofSeconds(30);
        System.out.println("04: " + duration4);
        // 根据毫秒获取实例
        Duration duration5 = Duration.ofMillis(4000);
        System.out.println("05: " + duration5);

        // 从一个字符串中获取一个实例,如:PnDTnHnMn.nS,其中一天被认为是24小时
        Duration duration6 = Duration.parse("P2D");
        System.out.println("06: " + duration6);

    }
}

输出结果:

01: PT24H
02: PT10H
03: PT20M
04: PT30S
05: PT4S
06: PT48H

Clock (时钟)

一种时钟,使用时区提供对当前时间戳、日期和时间的访问。

Period (周期)

在ISO-8601日历系统中以日期为基础的时间,如:“2年3个月4天”。

ZoneId (时区ID)

一个时区ID,如:Europe/Paris 。

ZoneOffset (时区偏移量)

与UTC/Greenwich的时区偏移量,如:+02:00 。

Year (年)

ISO-8601日历系统中的一年,如:2007年。

YearMonth (年-月)

ISO-8601日历系统中的年月,如:2007-12。

MonthDay (月-日)

ISO-8601日历系统中的一个月日,如:12-03。

OffsetDateTime (带偏移量的日期/时间)

在ISO-8601日历系统中带UTC/Greenwich偏移的日期时间,如:2007-12-03T10:15:30+01:00。

OffsetTime (带偏移的时间)

在ISO-8601日历系统中带UTC/Greenwich偏移的时间,如:10:15:30+01:00。

ZonedDateTime (带时区的日期-时间)

ISO-8601日历系统中带有时区的日期时间,如:2007-12-03T10:15:30+01:00 Europe/Paris。

DayOfWeek (星期枚举类)

星期几,如:“星期二”。

Month (月份枚举类)

一个月份,如:“七月”。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,290评论 6 491
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,107评论 2 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 156,872评论 0 347
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,415评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,453评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,784评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,927评论 3 406
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,691评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,137评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,472评论 2 326
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,622评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,289评论 4 329
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,887评论 3 312
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,741评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,977评论 1 265
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,316评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,490评论 2 348

推荐阅读更多精彩内容