本小节我们将学习 Java 中的日期和时间,日期和时间在我们的实际开发中非常常用,例如用户的注册、数据的增删改、对敏感信息的操作等等都需要记录下日期和时间。通过本小节的学习,你将了解到什么是日期、什么是时间、什么是时区,Java 中 Date 类的 API 介绍,Calendar 日历类的使用,LocalDateTime 类的相关 API 介绍等内容。

1. 什么是日期和时间

日期指的是某一天,例如:

  • 2020-10-24:2020 年 10 月 24 日;
  • 1998-6-14:1998 年 6 月 14 日。

时间就是指某一个时刻,它分为两种,一种是带日期的时间,另外一种是不带日期的时间,例如:

  • 2020-10-24 08:30:23:2020 年 10 月 24 日 8 时 30 分 23 秒;
  • 11:22:33:11 时 22 分 33 秒。

    2. 什么是时区

    我们知道,地球上的不同地区是有时差的,因此想要准确定位一个时刻,还需要加上时区。
    时区有以下 3 种表示方式:
  1. GMT 或者 UTC 加时区偏移表示:例如:GMT+08:00 或者 UTC+08:00 表示东八区;
  2. 缩写表示:例如:CST 表示 China Standard Time(中国标准时间),但是此缩写也可表示 Central Standard Time USA(美国中部时间),容易混淆不推荐使用;
  3. 洲 / 城市:例如:Asia/Shanghai 表示上海所在地的时区。注意城市名称不是任意的城市,而是由国际标准组织规定的城市。

    3. Date 类的使用

    java.util.Date 类日期表示特定的时间瞬间,精度为毫秒。我们下面来看一下这个类的构造方法和常用方法。

    3.1 构造方法

  • Date():创建一个对应当前时间的日期对象;
  • Date(long date):创建指定毫秒数的日期对象。

由于其他 4 个构造方法已经过期,这里我们不进行介绍。

3.2 常用方法

  • String toString():将此日期对象转换为以下形式的字符串:星期 月 日 时:分: 秒 时区 年;
  • long getTime():返回此日期对象表示的自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数;
  • void setTime():将此日期对象设置为表示 1970 年 1 月 1 日 00:00:00 GMT 之后的时间点(毫秒)。

大多数其他方法都已经过期,此处不再一一列举,可翻阅官方文档以了解更多内容。

Tips:除了 java.util 包下的 Date 类,在 java.sql 包下也有一个 Date 类。它是对应数据库字段的日期类型的类,与数据库交互的时候才会用到,由于目前我们不涉及数据库相关知识,此处做一个了解即可。我们更常用的还是 java.util 包下的 Date 类。

3.3 实例

创建日期对象,并打印 toString() 方法的结果:

  1. import java.util.Date;
  2. public class DateDemo1 {
  3. public static void main(String[] args) {
  4. // 实例化一个date对象
  5. Date date = new Date();
  6. // 调用 toString() 方法
  7. String s = date.toString();
  8. System.out.println(s);
  9. }
  10. }

运行结果:

  1. Wed Jun 10 10:21:10 CST 2020

我执行代码的时间是 2020 年 06 月 10 日 10:22:10 星期三,因此得到了如上的运行结果。
调用 getTime() 方法获取当前日期对象自 1970 年 1 月 1 日 00:00:00 GMT 以来的毫秒数:

  1. import java.util.Date;
  2. public class DateDemo2 {
  3. public static void main(String[] args) {
  4. // 实例化一个date对象
  5. Date date = new Date();
  6. // 调用 getTime() 方法
  7. long time = date.getTime();
  8. System.out.println(time);
  9. }
  10. }

运行结果:

  1. 1591755946922

4. Calendar 类的使用

Calendar 类是一个抽象类,它提供了一些方法,用于在特定的时间瞬间与一组日历字段(如年、月、月、日、小时等)之间进行转换,以及用于处理日历字段(如获取下一周的日期)。

4.1 实例化

由于 Calendar 类是一个抽象类,不能直接实例化,想要获取其实例对象通常有两种方法:

  1. 使用 Calendar.getInstance() 方法(更常用);
  2. 调用它的子类的 GregorianCalendar 的构造方法。

实例如下:

  1. Calendar calendar = Calendar.getInstance();

4.3 常用方法

  • static Calendar getInstance():使用默认时区和区域设置获取日历;
  • int get(int field):返回给定日历字段的值;
  • void set(int field, int value):将给定的日历字段设置为给定值。(此外,set() 还有很多重载方法)

get(int field) 和 set(int field, int value) 方法的 field 参数是 int 类型,我们可以使用 Calendar 类下的一些静态字段来表示,如下是官方文档关于 Calendar 类的部分静态字段的截图:
3.jpg
更多常用方法和静态字段请查阅官方文档

4.3 实例

4.3.1 get () 方法实例

  1. import java.util.Calendar;
  2. public class CalendarDemo1 {
  3. public static void main(String[] args) {
  4. Calendar calendar = Calendar.getInstance();
  5. // 获取今天是这一周的第几天
  6. int i = calendar.get(Calendar.DAY_OF_WEEK);
  7. // 获取今天是这一月的第几天
  8. int i1 = calendar.get(Calendar.DAY_OF_MONTH);
  9. // 获取今天是这一月的第几周
  10. int i2 = calendar.get(Calendar.DAY_OF_WEEK_IN_MONTH);
  11. // 获取今天是这一年的第几天
  12. int i3 = calendar.get(Calendar.DAY_OF_YEAR);
  13. System.out.println("今天是这一周的第" + i + "天");
  14. System.out.println("今天是这一月的第" + i1 + "天");
  15. System.out.println("今天是这一月的第" + i2 + "周");
  16. System.out.println("今天是这一年的第" + i3 + "天");
  17. }
  18. }

运行此段代码的时间是 2020 年 06 月 10 日,运行结果如下:

  1. 今天是这一周的第4
  2. 今天是这一月的第10
  3. 今天是这一月的第2
  4. 今天是这一年的第162

通过调用 get() 方法,我们很方便地获取到了当前时间在日历上是第几天。要特别注意的是,获取月份,返回的值是从 0 开始的(0 ~ 11),依次表示 1 月到 12 月;获取一周的第 n 天,这里的返回值为 1~7,1 表示周日,2 表示周一,以此类推。

4.3.2 set () 方法实例

  1. import java.util.Calendar;
  2. public class CalendarDemo2 {
  3. public static void main(String[] args) {
  4. Calendar calendar = Calendar.getInstance();
  5. // 设置2022年:
  6. calendar.set(Calendar.YEAR, 2022);
  7. // 设置9月: (8表示9月)
  8. calendar.set(Calendar.MONTH, 8);
  9. // 设置9日:
  10. calendar.set(Calendar.DATE, 9);
  11. // 设置时间:
  12. calendar.set(Calendar.HOUR_OF_DAY, 0);
  13. calendar.set(Calendar.MINUTE, 0);
  14. calendar.set(Calendar.SECOND, 0);
  15. System.out.println(calendar.getTime().toString());
  16. }
  17. }

运行结果:

  1. Fri Sep 09 00:00:00 CST 2022

上面代码分别设置了日历的年、月、日、时、分、秒,Calendar.getTime() 可以将一个 Calendar 对象转换成 Date 对象,最后再打印这个对象。

5. Java8 后新的日期和时间 API

5.1 为什么要提供新的 API

在 Java8 以后,提供了新的日期和时间 API,旧 API 的如下缺点得到了解决:

  • 可变性:旧的 API 日期和时间是可变的,日期和时间这样的类应该是不可变的;
  • 偏移性:Date 中的年份是从 1990 年开始,月份是从 0 开始,星期天是用 1 表示的,不了解 API 的开发者很容易用错;
  • 格式化:SimpleDateFormat 只能用于格式化 Date 类型,不能格式化 Calendar 类型。

    5.2 新 API 概述

    新的日期时间 API 吸取了 Joda-Time 的精华,提供了更优秀易用的 API,位于 java.time 包中,包含了 LocalTime(本地时间)、LocalDate(本地日期)、LocalDateTime(本地日期时间)、ZonedDateTime(带时区的日期时间)和 Duration(时间间隔)类。
    而 java.util.Date 类下面增加了 toInstant() 方法,用于把 Date 转换为新的类型。这些 API 大大简化了日期时间的运算。
    对偏移性的不合理设计也有修正:月份使用 1~12 表示 1 月 到 12 月,星期使用 1 ~ 7 表示星期一到星期天。
    另外,使用了新的 DateTimeFormatter 来取代旧的 SimpleDateFormat。

    5.3 LocalDateTime 相关类的使用

    ```java import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime;

public class LocalDateTimeDemo1 {

  1. public static void main(String[] args) {
  2. // 获取当前日期
  3. LocalDate localDate = LocalDate.now();
  4. // 获取当前时间
  5. LocalTime localTime = LocalTime.now();
  6. // 获取当前日期和时间
  7. LocalDateTime localDateTime = LocalDateTime.now();
  8. // 打印
  9. System.out.println(localDate);
  10. System.out.println(localTime);
  11. System.out.println(localDateTime);
  12. }

}

  1. 运行结果:
  2. ```java
  3. 2020-06-10
  4. 14:17:48.618294
  5. 2020-06-10T14:17:48.618421

在实际开发中,LocalDateTime 相较于 LocalDate 和 LocalTime 更加常用。
本地日期和时间通过 now() 获取到的总是以当前默认时区返回的。
另外,可以使用 of() 方法来设置当前日期和时间:

  1. // 2020-9-30
  2. LocalDate date = LocalDate.of(2020, 9, 30);
  3. // 14:15:10
  4. LocalTime time = LocalTime.of(14, 15, 10);
  5. // 将date和time组合成一个LocalDateTime
  6. LocalDateTime dateTime1 = LocalDateTime.of(date, time);
  7. // 设置 年、月、日、时、分、秒
  8. LocalDateTime dateTime2 = LocalDateTime.of(2020, 10, 21, 14, 14);

6. 小结

通过本小节的学习,我们知道了日期、时间和时区的基本概念,在 Java 8 之前,通过 Date 类、Calendar 类以及 SimpleDateFormat 类来操作日期和时间,Java 8 以后,java.time 包下新增了一批新的日期时间 API,修复了旧 API 的一些缺点,简化了开发者操作日期和时间的难度。本小节内容比较简单,梳理了 Java 对于日期时间处理的相关 API,大家参照文档,加以练习即可。