Java开发--6--日期与时间

1、格式

日期:2019-05-20
时间:05:20:13
日期时间:2019-05-20 05:20:13(中间必须有空格)

2、时区

以GMT或者UTC加时区偏移表示,例如:GMT+08:00或者UTC+08:00表示东八区。

GMT和UTC可以认为基本是等价的,只是UTC使用更精确的原子钟计时,每隔几年会有一个闰秒,我们在开发程序的时候可以忽略两者的误差,因为计算机的时钟在联网的时候会自动与时间服务器同步时间。

3、Java时间API

从Java 8开始,java.time包提供了新的日期和时间API,主要涉及的类型有:

本地日期和时间:LocalDateTimeLocalDateLocalTime
带时区的日期和时间:ZonedDateTime
时刻:Instant
时区:ZoneIdZoneOffset
时间间隔:Duration
以及一套新的用于取代SimpleDateFormat的格式化类型DateTimeFormatter。

4、LocalDateTime

表示一个本地日期和时间:

import java.time.*;

public class Main {

    public static void main(String[] args) {

        //由于每行代码执行需要时间,结果可能有毫秒级误差
        LocalDate d = LocalDate.now();    //当前日期
        LocalTime t = LocalTime.now();    //当前时间
        LocalDateTime dt = LocalDateTime.now();    //当前日期和时间

        //统一时间转换,无毫秒级误差
        LocalDateTime dt1 = LocalDateTime.now();    //当前日期和时间
        LocalDate d1 = dt.toLocalDate();    //转换到当前日期
        LocalTime t1 = dt.toLocalTime();    //转换到当前时间

        //指定日期和时间可以使用of方法
        LocalDate d2 = LocalDate.of(2020, 05, 20);
        LocalTime t2 = LocalTime.of(05, 20, 13);
        LocalDateTime dt2 = LocalDateTime.of(2020, 05, 20, 05, 20, 13);
        LocalDateTime dt3 = LocalDateTime.of(d2, t2);   //等同于dt2的结果

        //按照国际通用格式打印日期时间(ISO8601标准)
        System.out.println(d);
        System.out.println(t);
        System.out.println(dt);
        System.out.println(d1);
        System.out.println(t1);
        System.out.println(dt1);
        System.out.println(dt2);
        System.out.println(dt3);
    }
}

输出结果:

2020-08-01
14:12:06.957
2020-08-01T14:12:06.957
2020-08-01
14:12:06.957
2020-08-01T14:12:06.957
2020-05-20T05:20:13
2020-05-20T05:20:13

5、DateTimeFormatter

如果要自定义输出的格式,或者要把一个非ISO8601格式的字符串解析成LocalDateTime,可以使用新的DateTimeFormatter。

import java.time.*;
import java.time.format.*;

public class Main {

    public static void main(String[] args) {
        // 自定义格式化:
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm:ss");
        System.out.println(dtf.format(LocalDateTime.now()));

        // 用自定义格式解析:
        LocalDateTime dt2 = LocalDateTime.parse("2020/05/20 13:14:18", dtf);
        System.out.println(dt2);

        // 自定义时间加5天减3小时:
        LocalDateTime dt3 = dt2.plusDays(5).minusHours(3);
        System.out.println(dt3);

        // 自定义时间减1月
        LocalDateTime dt4 = dt2.minusMonths(1);
        System.out.println(dt4);
    }
}

输出结果:

2020/08/01 14:28:17
2020-05-20T13:14:18
2020-05-25T10:14:18
2020-04-20T13:14:18

对日期和时间进行调整则使用withXxx()方法,例如:withHour(15)会把10:11:12变为15:11:12

调整年:withYear()
调整月:withMonth()
调整日:withDayOfMonth()
调整时:withHour()
调整分:withMinute()
调整秒:withSecond()

import java.time.*;

public class Main {

    public static void main(String[] args) {
        // 用自定义格式解析:
        LocalDateTime dt2 = LocalDateTime.of(2020,05,20,13,14,18);
        System.out.println(dt2);

        // 修改自定义时间,日期变为31日
        LocalDateTime dt5 = dt2.withDayOfMonth(31);
        System.out.println(dt5);

        // 修改自定义时间,月份变为9
        LocalDateTime dt6 = dt2.withMonth(9);
        System.out.println(dt6);
    }
}

输出结果:

2020-05-20T13:14:18
2020-05-31T13:14:18
2020-09-20T13:14:18

其他时间计算,使用LocalDateTime的with()方法

import java.time.*;
import java.time.temporal.*;

public class Main {

    public static void main(String[] args) {
        // 本月第一天0:00时刻
        LocalDateTime firstDay = LocalDate.now().withDayOfMonth(1).atStartOfDay();
        System.out.println(firstDay);

        // 本月最后1天
        LocalDate lastDay = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
        System.out.println(lastDay);

        // 下月第1天
        LocalDate nextMonthFirstDay = LocalDate.now().with(TemporalAdjusters.firstDayOfNextMonth());
        System.out.println(nextMonthFirstDay);

        // 本月第1个周一
        LocalDate firstWeekday = LocalDate.now().with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY));
        System.out.println(firstWeekday);
    }
}

输出结果:

2020-08-01T00:00
2020-08-31
2020-09-01
2020-08-03

6、Duration和Period

Duration表示两个时刻之间的时间间隔。另一个类似的Period表示两个日期之间的天数

import java.time.*;

public class Main {

    public static void main(String[] args) {
        LocalDateTime start = LocalDateTime.of(2019, 11, 19, 8, 15, 0);
        LocalDateTime end = LocalDateTime.of(2020, 1, 9, 19, 25, 30);
        Duration d = Duration.between(start, end);    //两个时刻之间的时间间隔
        System.out.println(d);

        Period p = LocalDate.of(2019, 11, 19).until(LocalDate.of(2020, 1, 9));
        System.out.println(p);     //两个日期之间的天数
    }
}

输出结果:

PT1235H10M30S    //国际通用格式,表示1235小时10分钟30秒
P1M21D   //国际通用格式,表示1个月21天

7、ZonedDateTime

ZonedDateTime表示一个带时区的日期和时间。可以简单地把ZonedDateTime理解成LocalDateTime加ZoneId。ZoneId是java.time引入的新的时区类,注意和旧的java.util.TimeZone区别。

import java.time.*;

public class Main {

    public static void main(String[] args) {
        //默认时区
        ZonedDateTime zbj = ZonedDateTime.now();
        //用指定时区获取当前时间
        ZonedDateTime zny = ZonedDateTime.now(ZoneId.of("America/New_York"));
        
        System.out.println(zbj);
        System.out.println(zny);
    }
}

输出结果:
虽然它们时区不同,但表示的时间都是同一时刻(毫秒数不同是执行语句时的时间差)

2020-08-01T14:49:58.767+08:00[Asia/Shanghai]
2020-08-01T02:49:58.771-04:00[America/New_York]

8、时区转换

要转换时区,首先需要有一个ZonedDateTime对象,然后,通过withZoneSameInstant()将关联时区转换到另一个时区,转换后日期和时间都会相应调整。

实例:北京时间转换为纽约时间

import java.time.*;

public class Main {

    public static void main(String[] args) {
        //以中国时区获取当前时间
        ZonedDateTime zbj = ZonedDateTime.now(ZoneId.of("Asia/Shanghai"));
        //转换为纽约时间
        ZonedDateTime zny = zbj.withZoneSameInstant(ZoneId.of("America/New_York"));

        System.out.println(zbj);
        System.out.println(zny);
    }
}

输出结果:

2020-08-01T15:12:13.839+08:00[Asia/Shanghai]
2020-08-01T03:12:13.839-04:00[America/New_York]

9、DateTimeFormatter

对ZonedDateTime或LocalDateTime进行格式化,需要使用DateTimeFormatter类。DateTimeFormatter可以通过格式化字符串和Locale对日期和时间进行定制输出。

import java.time.*;
import java.time.format.*;
import java.util.Locale;

public class Main {

    public static void main(String[] args) {
        ZonedDateTime zdt = ZonedDateTime.now();
        var formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm ZZZZ");
        System.out.println(formatter.format(zdt));

        var zhFormatter = DateTimeFormatter.ofPattern("yyyy MMM dd EE HH:mm", Locale.CHINA);
        System.out.println(zhFormatter.format(zdt));

        var usFormatter = DateTimeFormatter.ofPattern("E, MMMM/dd/yyyy HH:mm", Locale.US);
        System.out.println(usFormatter.format(zdt));
    }
}

输出结果:

2020-08-01T07:19 GMT
2020 801 周六 07:19
Sat, August/01/2020 07:19

10、Instant

Instant表示高精度时间戳,它可以和ZonedDateTime以及long互相转换。

import java.time.*;

public class Main {

    public static void main(String[] args) {
        //当前时间戳
        Instant now = Instant.now();
        System.out.println(now.getEpochSecond()); //秒级时间戳
        System.out.println(now.toEpochMilli()); //毫秒级时间戳

        //给时间戳附加时区,转换为带时区时间
        long a = now.getEpochSecond();    //这里必须是秒级时间戳
        Instant ins = Instant.ofEpochSecond(a);
        ZonedDateTime zdt = ins.atZone(ZoneId.systemDefault());
        System.out.println(zdt);
    }
}

输出结果:

1596267222
1596267222396
2020-08-01T15:33:42+08:00[Asia/Shanghai]

你可能感兴趣的:(Java开发)