天天看点

java8的新时间与日期的API

新的时间和日期API

在Java 8之前,所有关于时间和日期的API都存在各种使用方面的缺陷,主要有:

  • Java的

    java.util.Date

    java.util.Calendar

    类易用性差,不支持时区,而且他们都不是线程安全的;
  • 用于格式化日期的类

    DateFormat

    被放在

    java.text

    包中,它是一个抽象类,所以我们需要实例化一个

    SimpleDateFormat

    对象来处理日期格式化,并且

    DateFormat

    也是非线程安全,这意味着如果你在多线程程序中调用同一个

    DateFormat

    对象,会得到意想不到的结果。
  • 对日期的计算方式繁琐,而且容易出错,因为月份是从0开始的,从

    Calendar

    中获取的月份需要加一才能表示当前月份。

LocalDate,LocalTime

初始化:

LocalDate ld = LocalDate.of(2018,9,9);

LocalTime lt = LocalTime.of(12,12,12);

获取当前时间:

ld = LocalDate.now();

lt = LocalTime.now();

查看详情

int year = ld.getYear();

Month month = ld.getMonth();

int day = ld.getDayOfMonth();

DayOfWeek weekday = ld.getDayOfWeek();

int hour = lt.getHour();

int minute = lt.getMinute();

int second = lt.getSecond();

LocalDateTime

初始化

LocalDate ld = LocalDate.of(2018,9,9);

LocalTime lt = LocalTime.of(12,12,12);

LocalDateTime ldt = ld.atTime(lt);

LocalDateTime ldt1 = lt.atDate(ld);

localDateTime => localDate/localTime

ld = ldt.toLocalDate

lt = ldt.toLocalTime

parse

String => LocalDateTime

String s = “2013-01-02 12:22:22”;

DateTimeFormatter df = DateTimeFormatter.ofPattern(“yyyy-MM-dd HH:mm:ss”);

LocalDateTime ldt = LocalDateTime.parse(s,df);

String => LocalDate/LocalTime

String sdate = “2013-01-02”;

String stime = “22:22:22”;

LocalDate ld = LocalDate.parse(sdate);

LocalTime lt = LocalTime.parse(stime);

Instant

Instant

用于表示一个时间戳,它与我们常使用的

System.currentTimeMillis()

有些类似,不过Instant可以精确到纳秒(Nano-Second),

System.currentTimeMillis()

方法只精确到毫秒(Milli-Second)。如果查看

Instant

源码,发现它的内部使用了两个常量,seconds表示从1970-01-01 00:00:00开始到现在的秒数,nanos表示纳秒部分(nanos的值不会超过999,999,999)。

Instant

除了使用

now()

方法创建外,还可以通过

ofEpochSecond

方法创建:

Instant instant = Instant.ofEpochSecond(120, 100000);

ofEpochSecond()

方法的第一个参数为秒,第二个参数为纳秒,上面的代码表示从1970-01-01 00:00:00开始后两分钟的10万纳秒的时刻

Duration

Duration

的内部实现与

Instant

类似,也是包含两部分:seconds表示秒,nanos表示纳秒。两者的区别是

Instant

用于表示一个时间戳(或者说是一个时间点),而

Duration

表示一个时间段,所以

Duration

类中不包含

now()

静态方法。可以通过

Duration.between()

方法创建

Duration

对象:

LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0); // 2017-01-05 10:07:00

LocalDateTime to = LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0); // 2017-02-05 10:07:00

Duration duration = Duration.between(from, to); // 表示从 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这段时间

long days = duration.toDays(); // 这段时间的总天数

long hours = duration.toHours(); // 这段时间的小时数

long minutes = duration.toMinutes(); // 这段时间的分钟数

long seconds = duration.getSeconds(); // 这段时间的秒数

long milliSeconds = duration.toMillis(); // 这段时间的毫秒数

long nanoSeconds = duration.toNanos(); // 这段时间的纳秒数

Duration

对象还可以通过

of()

方法创建,该方法接受一个时间段长度,和一个时间单位作为参数:

Duration duration1 = Duration.of(5, ChronoUnit.DAYS); // 5天

Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS); // 1000毫秒

Period

Period

在概念上和

Duration

类似,区别在于

Period

是以年月日来衡量一个时间段,比如2年3个月6天:

Period period = Period.of(2, 3, 6);

Period

对象也可以通过

between()

方法创建,值得注意的是,由于

Period

是以年月日衡量时间段,所以

between()

方法只能接收

LocalDate

类型的参数:

Period period2 = Period.between(LocalDate.of(2017, 1, 5),LocalDate.of(2017, 2, 5));

Period

对象可以获得时间段的长度:

int dayP2 = period2.getDays();

int monthP2 = period2.getMonths();

int yearP2 = period2.getYears()

注意,

Period

获得的时间段长度不是总的长度,如:

Period period2 = Period.between(LocalDate.of(2017, 1, 5),LocalDate.of(2017, 2, 5));

int day = period2.getDays(); // day=0

时区

参考

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;

public class LocalDateAndTime {
    public static void main(String[] args) throws Exception {
        LocalDate ld = LocalDate.of(2019,3,10);
        LocalTime lt = LocalTime.of(11,12,12);
        int year = ld.getYear();
        System.out.println("年:" + year);
        Month month = ld.getMonth();
        System.out.println("月:" + month);
        int day = ld.getDayOfMonth();
        System.out.println("日" + day);
        DayOfWeek weekday = ld.getDayOfWeek();
        System.out.println("周" + weekday);
        int hour = lt.getHour();
        System.out.println("小时" + hour);
        int minute = lt.getMinute();
        System.out.println("分钟" + minute);
        int second = lt.getSecond();
        System.out.println("秒" + second);
        System.out.println(ld);
        System.out.println(lt);

        String sdate = "2013-01-02";
        String stime = "22:22:22";
        ld = LocalDate.parse(sdate);
        lt = LocalTime.parse(stime);
        System.out.println(ld);
        System.out.println(lt);
        ld = LocalDate.now();
        lt = LocalTime.now();
        System.out.println(ld);
        System.out.println(lt);
        System.out.println("=========");



        String s = "2013-01-02 12:22:22";
        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime ldt = LocalDateTime.parse(s,df);
        System.out.println(ldt);
        ldt = lt.atDate(ld);
        System.out.println(ldt);
        ldt = ld.atTime(lt);
        System.out.println(ldt);

        ld = ldt.toLocalDate();
        lt = ldt.toLocalTime();
        System.out.println(ld);
        System.out.println(lt);
        System.out.println("=========");



        LocalDate hd = LocalDate.of(2019,3,10);
        System.out.println(ld == hd);
        System.out.println(ld.equals(hd));
        LocalDateTime ss = ld.atStartOfDay();
        System.out.println(ld);
        System.out.println(ld.withMonth(1));
        System.out.println(ld.withDayOfMonth(1));

        LocalDate md = LocalDate.now();
        System.out.println(ld);
        System.out.println(md);
        Long i = ld.toEpochDay()-md.toEpochDay()+1;
        Long j = hd.toEpochDay()-ld.toEpochDay();
        System.out.println(i);
        System.out.println(j);
        System.out.println((double)i/j*3);
        System.out.println(Math.floor((double)i/j*3));
        System.out.println(Math.ceil((double)i/j*3));
        System.out.println("=========");



        LocalDateTime from = LocalDateTime.of(2017, Month.JANUARY, 5, 10, 7, 0);    // 2017-01-05 10:07:00
        LocalDateTime to = LocalDateTime.of(2017, Month.FEBRUARY, 5, 10, 7, 0);     // 2017-02-05 10:07:00
        Duration duration = Duration.between(from, to);     // 表示从 2017-01-05 10:07:00 到 2017-02-05 10:07:00 这段时间

        long days = duration.toDays();              // 这段时间的总天数
        System.out.println("天数" + days);
        long hours = duration.toHours();            // 这段时间的小时数
        System.out.println("小时数" + hours);
        long minutes = duration.toMinutes();        // 这段时间的分钟数
        System.out.println("分钟数" + minutes);
        long seconds = duration.getSeconds();       // 这段时间的秒数
        System.out.println("秒数" + seconds);
        long milliSeconds = duration.toMillis();    // 这段时间的毫秒数
        System.out.println("毫秒数" + milliSeconds);
        long nanoSeconds = duration.toNanos();      // 这段时间的纳秒数
        System.out.println("纳秒数" + nanoSeconds);

        Duration duration1 = Duration.of(5, ChronoUnit.DAYS);       // 5天
        long days1 = duration1.toDays();              // 这段时间的总天数
        System.out.println("天数1:" + days1);
        Duration duration2 = Duration.of(1000, ChronoUnit.MILLIS);  // 1000毫秒
        long milliSeconds2 = duration2.toMillis();    // 这段时间的毫秒数
        System.out.println("毫秒数2:" + milliSeconds2);
        System.out.println("=========");


        Period period = Period.of(2, 3, 6);
        int dayP1 = period.getDays();
        int monthP1 = period.getMonths();
        int yearP1 = period.getYears();
        System.out.println("Period Days:" + dayP1 + ", Months:" + monthP1 + ", Years:" + yearP1);
        // 2017-01-05 到 2017-02-05 这段时间
        Period period2 = Period.between(LocalDate.of(2017, 1, 5),LocalDate.of(2017, 2, 5));
        int dayP2 = period2.getDays();
        int monthP2 = period2.getMonths();
        int yearP2 = period2.getYears();
        System.out.println("Period2 Days:" + dayP2 + ", Months:" + monthP2 + ", Years:" + yearP2);
        period2 = Period.between(LocalDate.of(2017, 1, 4),LocalDate.of(2020, 3, 5));
        dayP2 = period2.getDays();
        monthP2 = period2.getMonths();
        yearP2 = period2.getYears();
        System.out.println("Period2 Days:" + dayP2 + ", Months:" + monthP2 + ", Years:" + yearP2);
        System.out.println("Period获得的时间段长度不是总的长度,比如获得的天数,与月份和年份无关");
        System.out.println("=========");

    }
}