Java日期和时间类总结

文章目录

Date类

Java在java.util包中提供了Date类,这个类封装了当前的日期和时间。
JDK1.0开始就有了。
注意,Date不能实现国际化,偏移量也不统一,它的月份和小时都是从0开始的,月份的天数则是从1开始,年又是从1900开始的。

A year y is represented by the integer y - 1900.
A month is represented by an integer from 0 to 11; 0 is January, 1 is February, and so forth; thus 11 is December.
A date (day of month) is represented by an integer from 1 to 31 in the usual manner.
An hour is represented by an integer from 0 to 23. Thus, the hour from midnight to 1 a.m. is hour 0, and the hour from noon to 1 p.m. is hour 12.

该类的大部分方法都已过时。

常用的方法

Date类支持两种构造函数:

  1. 第一个构造函数,初始化对象的当前日期和时间。

Date()

  1. 下面的构造函数接收一个参数等于自1970年1月1日 00:00:00 起已经过的毫秒数

Date(long millisec)

以下方法还可以使用:

方法 描述
boolean after(Date date) 如果调用Date对象包含或晚于指定的日期则返回true,否则,返回false。
boolean before(Date date) 如果调用Date对象包含或早于日期指定的日期返回true,否则,返回false。
Object clone( ) 重复调用Date对象。
int compareTo(Date date) 调用对象的值与日期比较。如果这两个值相等返回0。如果调用对象是早于日期返回一个负值。如果调用对象迟于日期返回正值。
int compareTo(Object obj) 以相同的compareTo(Date)操作 如果obj是一个类日期。否则,它会抛出一个ClassCastException。
boolean equals(Object date) 如果调用Date对象包含相同的时间及日期指定日期则返回true,否则,返回false。
long getTime( ) 返回自1970年1月1日起已经过的毫秒数。
int hashCode( ) 返回调用对象的哈希代码。
void setTime(long time) 设置所指定的时间,这表示从1970年1月1日从午夜的时间和日期以毫秒为单位经过的时间。
String toString( ) 调用Date对象转换为字符串,并返回结果。

Calendar类

从JDK1.1开始有的。用于表示日历,指最通用的 Gregorian Calendar,即公历,它是一个抽象类,它是所有日历类的模板,所以不能使用构造函数来创建Calendar对象,但它提供了几个静态方法来获取Calendar对象,根据TimeZone,Locale类获取特定的Calendar,如果不指定,则使用默认的TimeZone,Locale来创建Calendar。

// 创建一个默认的Calendar对象
Calendar calendar = Calendar.getInstance()

// 从Calendar对象中取出Date对象
Date date = calendar.getTime()

// 通过Date对象获得对应的Calendar对象
// Calendar没有直接接收Date对象的构造函数,因此只能通过下面的方式
Calendar calendar1 = Calendar.getInstance();
calendar1.setTime(date);

注意的时间字段:
Calendar.MONTH 代表月份,月份的起始是0,0代表1月。
Calendar.HOUR 12小时制的小时
Calendar.HOUR_OF_DAY 24小时制的小时

常用的方法

方法 描述
add(int field, int amount) 根据日历规则,给指定的日历字段添加(正数)或减去(负数)指定的时间量
roll(int field, int amount) 与add方法类似,区别在于,加上amount后超过了该字段所能表示的最大范围时,也不会向上一个字段进位。
get(int field) 返回指定日历字段的值
getActualMaximum(int field) 获取指定日历字段可能拥有的最大值
getActualMinimum(int field) 获取指定日历字段可能拥有的最小值
set(int field, int value) 将给定日历字段设置为给定值
set(int year, int month, int date) 设置Calendar对象的年、月、日
set(int year, int month, int date, int hourOfDay, int minute, int second) 设置Calendar对象的年、月、日、时、分、秒

重要的注意点

add和roll方法的区别:

add(int field, int amount)方法
根据日历规则,给指定的日历字段添加(正数)或减去(负数)指定的时间量

  1. 当被修改的字段超出它允许的范围时,会发生进位,即上一级字段也会发生变化
  2. 如果下一级的字段也要发生变化,那么改字段也会修正到变化最小的值。
Calendar calendar = Calendar.getInstance();
calendar.set(2021, 0, 31);
System.out.println(calendar.getTime());
// 2021-1-31

calendar.add(Calendar.MONTH, 1);
System.out.println(calendar.getTime());
// 2021-02-28

calendar.add(Calendar.MONTH, 15);
System.out.println(calendar.getTime());
// 2022-05-28

roll(int field, int amount)

  1. 与add方法类似。区别在于,加上amount后超过了该字段所能表示的最大范围时,也不会向上一个字段进位。
  2. 下一级字段的处理规则与add方法相似
Calendar calendar = Calendar.getInstance();
calendar.set(2021, 0, 31);
calendar.roll(Calendar.MONTH, 15);
System.out.println(calendar.getTime());
// 2021-05-28

设置Calendar的容错性

调用set()方法来改变指定时间字段的值时,有可能会传入一个不合法的参数,例如 MONTH超过11。

通过调用 setLenient(boolean lenient) 方法实现:
它用于设置容错性,Calendar默认支持较好的容错性。通过setLenient(false)来关闭容错性,让它进行严格的参数检查。当超过指定时间字段允许的取值范围时,程序会抛出异常。

set()方法延迟修改

set(int field, int value)
尽管字段field是立即修改的,但该Calenda所代表的时间却不会立即修改,直到调用 get()、getTime()、getTimeInMillis()、add() 、roll() 时,才会重新计算日历的时间,这被称为set()方法的延迟修改。
优势: 多次调用set()方法不会触发多次不必要的计算(计算一个代表实际时间的long型整数)。

Java8新增的日期、时间包

Java8新增了一个 java.time的包。
同时也增加了一个 java.time.temporal 包,包括TemporalTemporalAdjuster 等接口,下面的一些类都实现了这些接口,使用的时候注意下。

Clock

获取指定时区的当前日期、时间。
该类可取代System类的currentTimeMillis()方法,而且提供了更多方法获取日期、时间。

Duration

代表持续时间。可以方便的获取一段时间。

Instant

代表一个具体的时刻,可以精确到纳秒。

LocalDate

代表一个不带时区的日期。
案例:

LocalDate today = LocalDate.now();
// 获取本周周一和周日
LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
LocalDate sunday = today.with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));

LocalTime

代表一个不带时区的时间。

LocalDateTime

代表一个不带时区的日期、时间。

MonthDay

代表月日。

Year

代表年。

YearMonth

代表年月。

ZonedDateTime

代表一个带时区的日期、时间

ZoneId

代表一个时区

DayOfWeek

枚举类,定义了周日到周六的枚举。

Month

枚举类,定义了一月到十二月的枚举。

相关案例如下:

public static void main(String[] args) {

        Clock clock = Clock.systemUTC();
        System.out.println("当前时刻:" + clock.instant());
        System.out.println(clock.getZone());
        // 获取clock对应的毫秒数,和System.currentTimeMillis()输出相同
        System.out.println(System.currentTimeMillis());
        System.out.println(clock.millis());

        Duration duration = Duration.ofSeconds(60100);
        System.out.println(duration.toHours());

        Instant instant = Instant.now();
        System.out.println(instant);
        System.out.println(instant.plusMillis(5));

        LocalDate localDate = LocalDate.now();
        System.out.println(localDate);

        // 设置为某一天
        System.out.println(LocalDate.of(2021, 1, 1));

        LocalTime localTime = LocalTime.now();
        System.out.println(localTime);

        Year year = Year.now();
        System.out.println(year);

        YearMonth yearMonth = YearMonth.now();
        System.out.println(yearMonth);

        MonthDay monthDay = MonthDay.now();
        System.out.println(monthDay);
        System.out.println(monthDay.withMonth(2).withDayOfMonth(4));

    }

LocalDateTime、LocalDate、Date的相互转换

LocalDateTime 转 LocalDate

直接调用 toLocalDate() 方法

LocalDateTime localDateTime = LocalDateTime.now();
LocalDate localDate = localDateTime.toLocalDate();

LocalDateTime 转 Date

在LocalDateTime 转 Date 时,需要使用到 Java 8的几个类

ZoneId/ZoneOffset:表示时区
ZonedDateTime: 表示特定时区的日期和时间
Instant:表示时刻,不直接对应年月日信息,需要通过时区转换

LocalDateTime localDateTime = LocalDateTime.now();
//获取系统默认时区
ZoneId zoneId = ZoneId.systemDefault();
//时区的日期和时间
ZonedDateTime zonedDateTime = localDateTime.atZone(zoneId);
//获取时刻
Date date = Date.from(zonedDateTime.toInstant());
System.out.println("格式化前:localDateTime:" + localDateTime + "  Date:" + date);
//格式化LocalDateTime、Date
DateTimeFormatter localDateTimeFormat = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
System.out.println("格式化后:localDateTime:" + localDateTimeFormat.format(localDateTime) + "  Date:" + dateFormat.format(date));

输出结果如下:

格式化前:localDateTime:2022-01-03T17:43:54.544  Date:Mon Jan 03 17:43:54 CST 2022
格式化后:localDateTime:2022-01-03 17:43:54  Date:2022-01-03 17:43:54

LocalDate 转 LocalDateTime

一般调用 atTime() 方法进行赋值

LocalDate localDate = LocalDate.now();
LocalDateTime localDateTime1 = localDate.atStartOfDay();
LocalDateTime localDateTime2 = localDate.atTime(8,20,33);
LocalDateTime localDateTime3 = localDate.atTime(LocalTime.now());

LocalDate 转 Date

先调用 atStartOfDay() 方法转 LocalDateTime 再转 Date

LocalDate localDate = LocalDate.now();
ZoneId zoneId = ZoneId.systemDefault();
Date date = Date.from(localDate.atStartOfDay().atZone(zoneId).toInstant());

Date 转 LocalDateTime

先转 ZonedDateTime 再转 LocalDateTime

Date date = new Date();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = date.toInstant().atZone(zoneId).toLocalDateTime();

Date 转 LocalDate

跟 LocalDate 同理

Date date = new Date();
ZoneId zoneId = ZoneId.systemDefault();
LocalDate localDate = date.toInstant().atZone(zoneId).toLocalDate();
上一篇:Java8新特性:时间格式化与时区的处理


下一篇:Java8新特性 -- 时间类