新特性08| 新日期时间API

简介

New date-time API is introduced in Java 8 to overcome the following drawbacks of old date-time API :

  1. Not thread safe : Unlike old java.util.Date which is not thread safe the new date-time API is immutable and doesn’t have setter methods.
  2. Less operations : In old API there are only few date operations but the new API provides us with many date operations.

(译文)Java8中引入了新的date-time API来解决老版本API中存在的以下缺陷:

  1. 线程不安全: 和以往版本中线程不安全的java.util.Date不同,新的date-time API是线程安全的,并且没有setter方法。
  2. 可操作性不强: 老版本API只有几个date操作函数,新版本中提供了大量的date操作函数。

说明

Java8在java.time报下引入了新版本的date-time API,最重要的两个类如下:

  1. Local: 简化了的date-time API,没有了复杂的时区处理;
  2. Zoned: 通过指定的时区处理日期时间。

具体使用

  1. LocalDate/LocatTime and LocalDateTime API : 当不需要处理时区时。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    import java.time.LocalDate;
    import java.time.LocalDateTime;
    import java.time.LocalTime;
    import java.time.Month;
    import java.time.format.DateTimeFormatter;

    public class DateTest {

    public static void LocalDateTimeApi() {

    // 打印当前日期
    LocalDate date = LocalDate.now();
    System.out.println("当前日期: " + date);


    // 打印当前时间
    LocalTime time = LocalTime.now();
    System.out.println("当前时间: " + time);


    // 打印当前日期T时间
    LocalDateTime current = LocalDateTime.now();
    System.out.println("当前日期和时间 : " + current);


    // 以指定格式打印当前DateTime
    DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");

    String formatedDateTime = current.format(format);

    System.out.println("指定格式: " + formatedDateTime);


    // 打印当前月、天和秒
    Month month = current.getMonth();
    int day = current.getDayOfMonth();
    int seconds = current.getSecond();
    System.out.println("月 : " + month + " 天 : " + day + " 秒 : " + seconds);

    // 打印指定日期
    LocalDate date2 = LocalDate.of(1899, 11, 29);
    System.out.println("FCB创立时间 :" + date2);

    // 用当前时间补充打印日期
    LocalDateTime specificDate = current.withYear(2012);

    System.out.println("以当前时间指定日期 : " + specificDate);
    }

    public static void main(String[] args) {
    LocalDateTimeApi();
    }
    }

输出:

1
2
3
4
5
6
7
当前日期: 2019-08-25
当前时间: 08:28:17.584
当前日期和时间 : 2019-08-25T08:28:17.585
指定格式: 25-08-2019 08:28:17
月 : AUGUST 天 : 25 秒 : 17
巴萨创立时间 :1899-11-29
以当前时间指定日期 : 2012-08-25T08:28:17.585
  1. Zoned date-time API : 当需要考虑时区时
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    import java.time.LocalDateTime;
    import java.time.ZoneId;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeFormatter;

    public class ZoneTest {

    // 获取带时区的日期和时间
    private static void ZonedTimeAndDate() {
    LocalDateTime date = LocalDateTime.now();
    // 指定格式
    DateTimeFormatter format = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss");
    String formattedCurrentDate = date.format(format);

    System.out.println("格式化后的日期和时间 : " + formattedCurrentDate);

    // 获取当前时区
    ZonedDateTime currentZone = ZonedDateTime.now();
    System.out.println("当前时区: " + currentZone.getZone());

    // 获取指定地方时区的时间
    ZoneId tokyo = ZoneId.of("Asia/Tokyo");
    ZonedDateTime tokyoZone = currentZone.withZoneSameInstant(tokyo);
    System.out.println("东京时间: " + tokyoZone);

    //格式化日期和时间
    String formatedDateTime = tokyoZone.format(format);
    System.out.println("格式化后的东京时间: " + formatedDateTime);

    }

    public static void main(String[] args) {
    ZonedTimeAndDate();
    }
    }

输出:

1
2
3
4
格式化后的日期和时间 : 25-08-2019 08:43:25
当前时区: Asia/Shanghai
东京时间: 2019-08-25T09:43:25.474+09:00[Asia/Tokyo]
格式化后的东京时间: 25-08-2019 09:43:25
  1. Period类和Duration类 :
    Period : 计算日期差(差了几年几月几日);
    Duration : 计算时间差(差了几时几分几秒);
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    import java.time.*;

    public class PeriodAndDurationTest {

    private static void checkingPeriod() {
    // 当前日期
    LocalDate date1 = LocalDate.now();
    // 指定日期
    LocalDate date2 = LocalDate.of(2018, Month.JULY, 24);

    // 计算两个日期之间的差(用第2个参数减第1个参数),结果表示为P(num)Y(num)M(num)D
    // 上面num表示数字,Y表示年,M表示月,D表示天
    Period gap = Period.between(date2, date1);
    System.out.println("date1和date2中间差了: " + gap);
    }

    private static void checkingDuration() {
    // 当前时间
    LocalTime time1 = LocalTime.now();
    System.out.println("当前时间: " + time1);

    // 设定5小时间隔
    Duration fiveHours = Duration.ofHours(5);

    // 将5小时加到当前时间
    LocalTime time2 = time1.plus(fiveHours);
    System.out.println("当前时间加上5小时后: " + time2);

    // 计算两个时间差(用第2个参数减第1个参数),结果表示为PT(num)H(num)M(num)s
    // 上面num表示数字,H表示时,M表示分,S表示秒
    Duration gap1 = Duration.between(time1, time2);
    System.out.println("time1和time2的时间差: " + gap1);

    // 更详细的时间差
    LocalTime time3 = LocalTime.of(16, 20, 18);
    Duration gap2 = Duration.between(time1, time3);
    System.out.println("time1和time3的时间差: " + gap2);
    }

    public static void main(String[] args) {
    checkingPeriod();
    checkingDuration();
    }
    }

输出:

1
2
3
4
5
date1和date2中间差了: P1Y1M1D
当前时间: 09:51:04.019
当前时间加上5小时后: 14:51:04.019
time1和time2的时间差: PT5H
time1和time3的时间差: PT6H29M13.981S
  1. ChronoUnits枚举类 : Java8使用ChronoUnit枚举类替代旧API中表示天、月等类。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import java.time.LocalDate;
    import java.time.temporal.ChronoUnit;

    public class ChronoUnitTest {

    public static void checkingChronoEnum() {
    LocalDate date = LocalDate.now();
    System.out.println("当前日期是 :" + date);

    // 在当前日期上加2年
    LocalDate year = date.plus(2, ChronoUnit.YEARS);
    System.out.println("加上2年后: " + year);

    // 在当前日期上加1个月
    LocalDate nextMonth = date.plus(1, ChronoUnit.MONTHS);
    System.out.println("加上1个月后: " + nextMonth);

    // adding 1 week to the current date
    // 在当前日期上加1周
    LocalDate nextWeek = date.plus(1, ChronoUnit.WEEKS);
    System.out.println("加上1周后:" + nextWeek);

    // 在当前日期上加20年
    LocalDate Decade = date.plus(2, ChronoUnit.DECADES);

    System.out.println("加上20年后: " + Decade);
    }

    public static void main(String[] args) {
    checkingChronoEnum();
    }
    }

输出:

1
2
3
4
5
当前日期是 :2019-08-25
加上2年后: 2021-08-25
加上1个月后: 2019-09-25
加上1周后:2019-09-01
加上20年后: 2039-08-25
  1. TemporalAdjusters类: 可以执行多个与日期相关的操作
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    import java.time.DayOfWeek;
    import java.time.LocalDate;
    import java.time.temporal.TemporalAdjusters;

    public class TemporalAdjustersTest {

    private static void checkingAdjusters() {

    LocalDate date = LocalDate.now();
    System.out.println("当前日期: " + date);

    // 获取下个月的第一天
    LocalDate dayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth());
    System.out.println("下一个月的第一天: " + dayOfNextMonth);

    // 获取下个周六
    LocalDate nextSaturday = date.with(TemporalAdjusters.next(DayOfWeek.SATURDAY));
    System.out.println("下个周六: " + nextSaturday);

    // 获取当前月的第一天
    LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth());
    System.out.println("当前月的第一天: " + firstDay);

    // 获取当前月的最后一天
    LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth());
    System.out.println("当前月的最后一天: " + lastDay);
    }

    public static void main(String[] args) {
    checkingAdjusters();
    }
    }

输出:

1
2
3
4
5
当前日期: 2019-08-25
下一个月的第一天: 2019-09-01
下个周六: 2019-08-31
当前月的第一天: 2019-08-01
当前月的最后一天: 2019-08-31

更多详细内容参见官方文档

码哥 wechat
欢迎关注个人订阅号:「码上行动GO」