MENU

Java-53 日期时间

November 8, 2023 • Read: 68 • Java阅读设置

日期时间

JDK8之前的日期时间API

1 java.lang.System中的currentTimeMillis()

  • public static long currentTimeMillis():返回当前时间与1970年1月1日0时0分0秒的毫秒差值。
    2023-11-08T04:06:23.png
    2023-11-08T04:09:03.png

2 java.util.Date

Date类表示特定的时间时刻,精度为毫秒级。

常用的结构为两个构造器和两个方法:

  • 构造器:

    • public Date():构造一个表示当前时间的Date对象。
    • public Date(long date):构造一个表示指定毫秒数(该毫秒数表示的与1970年1月1日的毫秒差)对应的时间的Date对象。
  • 方法:

    • public long getTime():返回对应Date对象对应的与1970年1月1日的毫秒差值。
      2023-11-08T04:13:32.png
    • public String toString():返回对应Date对象对应的时间,显示的格式包括年、月、日、星期、小时、分钟、秒、时区。这也是直接打印对应Date对象的返回值。
      2023-11-08T04:15:41.png
  • 示例:
    2023-11-08T04:19:48.png

3 java.sql.Date

java.sql.Date类是java.util.Date的子类,是用于表示sql中date类型的数据对应的时间。

常用的结构包括一个构造器和一个方法:

  • 构造器:

    • public Date(long date):构造指定毫秒数的java.sql.Date对象,其中参数的毫秒数是自January 1, 1970, 00:00:00 GMT以来的毫秒数不超过8099年的毫秒数。负数表示从1970年过去某个时间到1970年1月1日00:00:00 GMT的毫秒数。
      2023-11-08T04:24:39.png
  • 方法:

    • public String toString():返回对应java.sql.Date对象表示的时间,格式为年-月-日,也是打印对应java.sql.Date对象的返回值。
      2023-11-08T04:28:44.png
  • 示例:
    2023-11-08T04:27:18.png
  • java.util.Date对象与java.sql.Date对象的转换

    • java.util.Date对象转换为java.sql.Date对象:他们之间的唯一联系就是都可以与毫秒数转换,因此,只要将对应java.util.Date对象先转换为对应的毫秒数(getTime)方法,再作为java.sql.Date对象的构造器的参数,即可完成对应转换。
    • java.sql.Date对象转换为java.util.Date对象:由于java.sql.Datejava.util.Date的子类,因此可以直接通过多态转换。

4 java.text.SimpleDateFormat

2023-11-09T03:18:19.png

SimpleDateFormat类可以理解为,对Date进行格式化和解析的类。

  • 格式化:Date--->指定格式的String
  • 解析:指定格式的String--->Date

SimpleDateFormat对象对应于针对某种格式的格式化和解析器,简单地说,SimpleDateFormat对象只能针对其对应的格式进行格式化和解析。

SimpleDateFormat实例化:

  • public SimpleDateFormat():默认空参构造器会构造一个针对默认格式的SimpleDateFormat对象,可以通过查看格式化后的Date对应的String来查看默认格式。
    2023-11-09T03:25:15.png
  • public SimpleDateFormat(String pattern):该构造器会根据指定的格式模式来构造指定格式的SimpleDateFormat对象,常用的格式为yyyy-MM-dd hh:mm:ss,设计格式模式具体参照官方文档。
    2023-11-09T03:25:03.png
    2023-11-09T03:25:33.png
    2023-11-09T03:25:47.png

格式化与解析方法:

  • public final String format(Date date):该方法能够格式化Date对象为对应的格式的字符串。该方法是SimpleDateFormat对象继承自抽象类java.text.DateFormat的。
    2023-11-09T03:27:49.png
  • public Date parse(String source):该方法能够将对应格式对应的字符串解析为对应的Date对象。该方法也是SimpleDateFormat对象继承自抽象类java.text.DateFormat的。
    2023-11-09T03:28:52.png

示例:

  • 默认格式:
    2023-11-09T03:29:15.png
  • 指定格式:
    2023-11-09T03:29:40.png

5 Calendar

Calendar是指java.util.Calendar,实质上是一个抽象类,该类能够将特定时间与日历中的属性相互转换,如YEAR、MONTH、DAY of MONTH、HOUR等,并且能够设置日历属性。
该类的对象可以理解为一个具有对应时间的所有日历属性的结构,该类的对象能够通过其属性来间接地表示其对应的时间。
2023-11-09T06:14:45.png

Calendar对象的构建:
由于Calendar是抽象类,没有直接对象,这里有两种方式创建Calendar对象:

  • 通过构建其子类GregorianCalendar的对象来实现Calendar对象的创建。
    2023-11-09T07:14:34.png
  • 通过使用Calendar的生成Calendar对象的静态方法public static Calendar getInstance()来实现Calendar对象的创建,其本质上仍是GregorianCalendar对象,只是该方法返回Calendar对象。
    2023-11-09T07:16:25.png

推荐使用第二种方式来创建Calendar对象,得到的Calendar对象是一个具有当前时间的所有日历属性的结构,该类的对象能够通过其属性来间接地表示其对应的当前的时间。

Calendar类对应的常用方法:

  • public abstract void add(int field, int amount):该方法能够对对应Calendar对象对应的时间对应的指定属性增加或减少对应的量(减少就是amount为负数)。
    2023-11-09T09:10:56.png
  • public int get(int field):该方法能够返回对应Calendar对象对应的时间对应的指定的日历属性值,参数field就是指定日历属性,直接通过传入Calendar类的静态属性来实现,返回的int型表示对应属性对应的值,可以通过查阅Calendar类的静态属性对应的int值来确定具体含义。
    2023-11-09T07:21:28.png
  • public void set(int field, int value):该方法能够设置对应Calendar对象对应的时间对应的指定的日历属性值。设置后也就改变了Calendar对象对应的时间。
    2023-11-09T07:22:43.png
  • public final Date getTime():该方法能够得到对应Calendar对象对应的时间对应的Date对象,相当于实现Calendar--->Date的转换。
    2023-11-09T07:23:56.png
  • public final void setTime(Date date):该方法能够将Date对象对应的时间转换为对应的Calendar对象,相当于实现Date--->Calendar的转换。
    2023-11-09T07:24:56.png

Calendar类对应的常用属性:

  • public static final int YEAR:年的表示,即表示Calendar对象对应的时间的年份。
    2023-11-09T07:26:51.png
  • public static final int MONTH:月的表示,注意一月对应的值为0,即表示Calendar对象对应的时间的月份。
    2023-11-09T07:26:37.png
  • public static final int DATE:一个月中的天数表示,等同于 DAY_OF_MONTH,即表示Calendar对象对应的时间的月份中的天数。
    2023-11-09T07:27:46.png
  • public static final int DAY_OF_MONTH:一个月中的天数表示,同上。
    2023-11-09T07:29:32.png
  • public static final int DAY_OF_YEAR:表示Calendar对象对应的时间是这一年的第几天。
    2023-11-09T07:30:48.png
  • DAY_OF_WEEK:表示Calendar对象对应的时间是这一周的第几天,默认周日是一周的第一天,即周日是1。
    2023-11-09T07:31:46.png
  • public static final int DAY_OF_WEEK_IN_MONTH:表示Calendar对象对应的时间是在这个月的第几周。负数表示从月末开始数。
    2023-11-09T07:32:41.png
  • public static final int WEEK_OF_MONTH:表示Calendar对象对应的时间是在这个月的第几周。
    2023-11-09T07:37:45.png
  • public static final int WEEK_OF_YEAR:表示Calendar对象对应的时间是在这一年的第几周。
    2023-11-09T07:38:19.png
  • public static final int HOUR:表示Calendar对象对应的时间在这一天的小时数,12进制。
    2023-11-09T07:39:05.png
  • public static final int HOUR_OF_DAY:同上,24进制。
    2023-11-09T07:39:27.png
  • public static final int MINUTE:表示Calendar对象对应的时间在这一天这一小时的分钟数。
    2023-11-09T07:40:02.png
  • public static final int SECOND:表示Calendar对象对应的时间在这一天这一小时这一分钟的秒数。
    2023-11-09T07:40:38.png
  • public static final int MILLISECOND:表示Calendar对象对应的时间在这一天这一小时这一分钟的毫秒数。
    2023-11-09T07:41:27.png

示例:
2023-11-09T07:42:49.png
2023-11-09T07:42:58.png
2023-11-09T07:43:11.png
2023-11-09T09:13:27.png

JDK8中的日期时间API

JDK8之前的日期时间API使用起来并不够方便:

  • 可变性:Calendar类对应的对象可以设置对应的时间的属性值,即修改对应的时间,但是这种修改体现出该类的可变性,即对时间的修改就是修改原来的时间。
    但是像日期和时间这样的数据,不可变更合适,也就是说,只要改变,就应该是生成了对应的新的对象而不影响原来的时间对应的对象。
  • 具有偏移量:Calendar对象的月份,一月对应的值是0,即每个月份对应的值是我们希望的值-1(不符合本地月份的值),另外,其显示的一周的天,周天是1,这也与我们希望的值不同。
  • 格式化有限:格式化只针对Date,而不能对Calendar进行格式化。
  • 线程不安全,且不能处理闰秒。闰秒理解为自动更新调整时间以保持时间的一致性的秒数(因为地球自转等原因会使得时间会有偏差)。

JDK8中新增了本地化时间日期API,这些API大大简化了日期时间和本地化的管理:
2023-11-09T09:46:44.png

  • java.time:包含值对象的基础包;
  • java.time.chrono:提供对不同的日历系统的访问;
  • java.time.format:格式化和解析时间和日期;
  • java.time.temporal:包括底层框架和扩展特性;
  • java.time.zone:包含时区支持的类。

其中,比较常用的是:java.timejava,format,也可能会用到java.temporal

1 LocalDate & LocalTime & LocalDateTime

LocalDate, LocalTime, LocalDateTimejava.time中的三个类,这三个类非常类似。

  • LocalDate表示的是ISO-8601日历系统中没有时区的日期,如2007-12-03。
    LocalDate表示的是不可变的日期对象,其仅表示日期,一般格式为:年-月-日,可以获取对应日期对应的其他属性值,比如day-of-year, day-of-week and week-of-year。
    LocalDate是不可变的,并且是线程安全的。
    2023-11-09T10:15:39.png
  • LocalTime表示的是ISO-8601日历系统中没有时区的时间,如10:15:30。
    LocalTime表示的是不可变的时间对象,其仅表示时间,一般格式为:时:分:秒,其表示的时间是纳秒精度的,因此纳秒精度的时间可以构建为该对象,也可以获取对应时间对应的其他属性,比如hour, minute, second, Nano。
    LocalTime也是不可变的,并且是线程安全的。
    2023-11-09T10:19:53.png
  • LocalDateTime表示的是ISO-8601日历系统中没有时区的日期和时间,如2007-12-03T10:15:30。
    LocalDateTime可以理解为LocalDateLocalTime的结合,可以获取对应日期和时间的其他属性(就是LocalDate和LocalTime的属性结合)。
    LocalDateTime也是不可变的,并且是线程安全的。
    2023-11-09T10:22:08.png

ISO-8601日历系统是国家标准化组织制定的现代公民的日期和时间表示法,也就是公历。

LocalDate & LocalTime & LocalDateTime的实例化
上述三个类的实例化都是主要使用对应的两个静态方法:

  • now():该方法会返回一个当前日期或时间或日期和时间的对应类对象。
    2023-11-09T10:26:07.png
    2023-11-09T10:26:16.png
    2023-11-09T10:26:25.png
  • of(argument):该方法会返回指定日期或时间或日期和时间的对应类对象。
    2023-11-09T10:27:22.png
    2023-11-09T10:27:36.png
    2023-11-09T10:27:59.png

示例:
2023-11-09T10:30:16.png
2023-11-09T10:32:28.png

LocalDate & LocalTime & LocalDateTime的方法
三个类对应的方法类似,区别仅在于针对日期或时间或日期和时间,简单地说,LocalDateTime对应的方法就是前两者的结合,前两者有的它都有。
根据方法的功能主要分为四类:获取其他属性值getField()、增加对应属性值plusField()、减少对应属性值minusField()、设置对应属性值withField()。注意,只要改变都会返回新的对应的对象,体现不可变性。

  • LocalDate:

    • 获取其他属性值,其中返回值为某个类时,表示返回对应的表示对应时间的枚举类对象,可以理解为返回对应的String
      2023-11-09T10:39:04.png
      2023-11-09T10:39:18.png
    • 增加对应属性值,生成新的对应对象:
      2023-11-09T10:41:06.png
    • 减少对应的属性值,生成新的对应对象:
      2023-11-09T10:41:36.png
    • 设置对应的属性值,生成新的对应对象:
      2023-11-09T10:42:21.png
  • LocalTime:

    • 获取其他属性值:
      2023-11-09T10:43:25.png
    • 增加对应属性值,生成新的对应对象:
      2023-11-09T10:44:11.png
    • 减少对应的属性值,生成新的对应对象:
      2023-11-09T10:44:24.png
    • 设置对应的属性值,生成新的对应对象:
      2023-11-09T10:44:39.png
  • LocalDateTime:

    • 获取其他属性值,其中返回值为某个类时,表示返回对应的表示对应时间的枚举类对象,可以理解为返回对应的String
      2023-11-09T10:46:45.png
    • 增加对应属性值,生成新的对应对象:
      2023-11-09T10:47:01.png
    • 减少对应的属性值,生成新的对应对象:
      2023-11-09T10:47:41.png
    • 设置对应的属性值,生成新的对应对象:
      2023-11-09T10:48:00.png

示例:
2023-11-09T10:51:57.png
2023-11-09T10:54:28.png
2023-11-09T10:56:02.png
2023-11-09T10:57:43.png

2 Instant

Instant是指java.time.Instant类,是表示面向机器的时间的类。类似于Date类。

Instant对象是表示时间线上的一个瞬时点,准确地说,是表示从1970年1月1日(UTC)开始的秒数,以毫秒为单位。这可能被用来记录应用程序中的事件时间戳。Instant类中有静态属性EPOCH来专门表示1970年1月1日(UTC)的时间,对于InstantEPOCH之后的瞬时点是正数(long型),EPOCH之前的瞬时点是负数(long型)。

Instant是不可变的,且线程安全的。

2023-11-10T03:22:05.png

1) 关于时间的基本常识

  • 秒、毫秒、微秒、纳秒的换算

    • 1s = 1000ms
    • 1ms = 1000us
    • 1us = 1000ns
  • 时区
    由于地球自转,地球上每个地区面向太阳和背向太阳的时刻各不相同,1884年国际子午线会议将地球分为24个区域,每个区域相差15个经度,从0°经线所在的零时区开始,向东和向西各有12个时区,中国北京就是东八区。

以零时区为标准,向东每跨一个时区就是增加一小时,向西每跨一个时区就是减一小时。例如零时区为早上八点,那么东八区就是下午四点,而西一区就是早上七点。

  • 时间标准

    • UTC(世界标准时间):UTC:协调世界时,又称 世界标准时间或世界协调时间,简称 UTC,是最主要的世界时间标准。其以原子时秒长为基础,在时刻上尽量接近于格林尼治标准时间。
    • GMT(格林尼治时间):格林尼治平时,又称 格林尼治平均时间或格林尼治标准时间,简称 GMT,是指位于英国伦敦郊区的皇家格林尼治天文台的标准时间,因为本初子午线被定义在通过那里的经线。
      理论上来说,格林尼治标准时间的正午是指当太阳横穿格林尼治子午线时(也就是在格林尼治上空最高点时)的时间。由于地球在它的椭圆轨道里的运动速度不均匀,这个时刻可能与实际的太阳时有误差,最大误差达16分钟。
      由于地球每天的自转是有些不规则的,而且正在缓慢减速,因此格林尼治时间已经不再被作为标准时间使用。现在的标准时间,是由原子钟报时的协调世界时(UTC)
    • CST(北京时间):北京时间,又称 中国标准时间。在时区划分上,属东八区,比协调世界时早 8 小时,记为:UTC+8

2) Instant实例化

  • public static Instant now():获得表示以UTC为标准的当前时间点的Instant对象。
    2023-11-10T03:38:21.png
  • public static Instant ofEpochMilli(long epochMilli):获得表示指定毫秒数对应的时间点的Instant对象。
    2023-11-10T03:43:18.png

3) Instant方法

  • public OffsetDateTime atOffset(ZoneOffset offset):对对应Instant对象对应的时间点添加偏移量以生成对应的新的时间点的对象。
    2023-11-10T03:47:09.png
  • public long toEpochMilli():返回对应Instant对象对应的时间点对应的毫秒数。
    2023-11-10T03:52:33.png

3 DateTimeFormatter

DateTimeFormatter是指java.time.format.DateTimeFormatter类,其类似于SimpleDateFormat类,是一个对表示日期或时间或日期和时间对象的格式化和解析器。

SimpleDateFormat类针对的是Date对象。
DateTimeFormatter类针对的是TemporalAccessor对象。而TemporalAccessor是一个接口,其典型实现类包括LocalDate, LocalTime, LocalDateTime等。因此,可以说DateTimeFormatter类针对的是LocalDate, LocalTime, LocalDateTime对象的格式化的类。

之所以没有强调其解析的作用,是因为,该类解析结果虽然是TemporalAccessor对象,但并不是LocalDate, LocalTime, LocalDateTime对象,而是Parsed对象。

DateTimeFormatter类与SimpleDateFormat类类似,每个对象是针对对应的一种格式来进行格式化和解析的。

1) DateTimeFormatter实例化
DateTimeFormatter实例化涉及格式的指定,根据能够指定的格式类型,可以通过三种方式实现DateTimeFormatter实例化:

  • 使用DateTimeFormatter类中提供的标准格式:DateTimeFormatter类中提供了标准格式对应的DateTimeFormatter对象,可以直接使用,具体可参照官方文档。
    2023-11-10T04:51:17.png
    2023-11-10T04:51:52.png
  • 使用DateTimeFormatter类中提供的本地格式:DateTimeFormatter类中提供了生成本地格式的对应对象方法,对应方法需要指定本地格式的样式,该样式是定义在FormatStyle的枚举类中,其中提供了FULL, LONG, MEDIUM, SHORT四种样式。注意对于DateTime不存在FULL样式,即不能指定FULL样式的DateTime的本地格式,会报错。
    2023-11-10T04:55:51.png
    2023-11-10T04:56:00.png

    • public static DateTimeFormatter ofLocalizedDate(FormatStyle dateStyle):创建指定日期样式的本地日期对应的DateTimeFormatter对象。
    • public static DateTimeFormatter ofLocalizedTime(FormatStyle timeStyle):创建指定时间样式的本地时间对应的DateTimeFormatter对象。
    • public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateTimeStyle):创建指定日期样式的本地日期和时间对应的DateTimeFormatter对象。
    • public static DateTimeFormatter ofLocalizedDateTime(FormatStyle dateStyle, FormatStyle timeStyle):创建指定日期和时间样式的本地日期和时间对应的DateTimeFormatter对象。
  • 使用自定义的格式:DateTimeFormatter类中提供了生成自定义格式的对应对象方法,对应方法需要指定自定义的格式模式字符串,如uuuu-MM-dd HH:mm:ss。如何自定义具体参照官方文档。
    2023-11-10T04:59:22.png

    • public static DateTimeFormatter ofPattern(String pattern):创建指定自定义格式的DateTimeFormatter对象。

2) 格式化和解析
类似于SimpleDateFormat对象,格式化使用对应的format()方法,解析使用对应的parse()方法:

  • public String format(TemporalAccessor temporal)
  • public TemporalAccessor parse(CharSequence text)

3) 示例

  • 标准格式:
    2023-11-10T05:02:31.png
  • 本地格式:

    • 日期:
      2023-11-10T05:03:08.png
    • 时间:
      2023-11-10T05:03:43.png
    • 日期和时间:
      2023-11-10T05:04:14.png
  • 自定义格式:
    2023-11-10T05:04:39.png

4 其他API

这里列举的最后两个是在java.time.temporal中,其他都是在java.time中。
2023-11-10T05:15:09.png

JDK8之前与之后日期时间类的转换:
2023-11-10T05:16:21.png

Last Modified: November 10, 2023