在开发中经常需要处理日期和时间,Java提供了一套专门用于处理日期时间的API,在日期时间类中了包含LocalDate类、LocalTime类、Instant类、Duration类以及Period类等,这些类都包含在java.time包中。

类的名称 功能描述
Instant 表示时刻,代表的是时间戳
LocalDate 不包含具体时间的日期
LocalTime 不包含日期的时间
LocalDateTime 包含了日期和时间
Duration 基于时间的值测量时间量
Period 计算日期时间差异,只能精确到年月日
Clock 时钟系统,用于查找当前时刻

Instant(时间戳)类

Instant 类代表的是某个时间。其内部是由两个Long字段组成,

第一部分是保存自标准Java计算时代(即1970年1月1日开始)至当前时间的秒数,即时间戳(Timestamp)。该时间戳表示从参考时间点开始经过的秒数。

第二部分是保存纳秒数。纳秒是时间的更精细单位,表示每秒钟的十亿分之一。

常用方法:

  • now():使用系统时钟获取当前瞬时。
  • now(Clock clock):使用指定时钟获取当前瞬时。
  • ofEpochSecond(long epochSecond):使用自标准Java计算时代开始的秒数获得一个Instant实例。
  • ofEpochMilli(long epochMilli):使用自标准Java计算时代开始的毫秒数获得一个Instant实例。
  • getEpochSecond():获取时间戳的秒数部分。
  • getNano():获取时间戳的纳秒数部分。
  • parse(CharSequence text):将表示时间的字符串转换为对应的Instant对象。
  • from(TemporalAccessor tenporal):从时间对象获取一个Instant的实例。
  • plusSeconds(long seconds) 和 plusMillis(long millis):在时间戳的基础上增加指定的秒数或毫秒数。
  • minusSeconds() 和 minusMillis():在时间戳的基础上减去指定的秒数或毫秒数。
  • isBefore() 和 isAfter() 方法:比较两个时间戳的先后顺序。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
import java.time.Clock;
import java.time.Instant;

public class InstantExample {
public static void main(String[] args) {
// 获取当前时间的瞬时实例
Instant now = Instant.now();
System.out.println("当前时间:" + now);

// 使用指定时钟获取当前时间的瞬时实例
Clock clock = Clock.systemUTC();
Instant nowWithClock = Instant.now(clock);
System.out.println("当前时间(使用指定时钟):" + nowWithClock);

// 使用从自标准Java计算时代开始的秒数创建Instant实例
Instant epochSecondInstant = Instant.ofEpochSecond(1234567890);
System.out.println("自1970年1月1日起的秒数对应的时间:" + epochSecondInstant);

// 使用从自标准Java计算时代开始的毫秒数创建Instant实例
Instant epochMilliInstant = Instant.ofEpochMilli(1627368000000L);
System.out.println("自1970年1月1日起的毫秒数对应的时间:" + epochMilliInstant);

// 获取时间戳的秒数部分
long seconds = now.getEpochSecond();
System.out.println("时间戳的秒数部分:" + seconds);

// 获取时间戳的纳秒数部分
int nanos = now.getNano();
System.out.println("时间戳的纳秒数部分:" + nanos);

// 将表示时间的字符串转换为Instant对象
String timeString = "2023-08-14T10:30:00Z";
Instant parsedInstant = Instant.parse(timeString);
System.out.println("解析后的时间:" + parsedInstant);

// 在时间戳的基础上增加指定的秒数或毫秒数
Instant plusSecondsInstant = now.plusSeconds(3600);
Instant plusMillisInstant = now.plusMillis(1000);
System.out.println("增加1小时后的时间:" + plusSecondsInstant);
System.out.println("增加1秒后的时间:" + plusMillisInstant);

// 在时间戳的基础上减去指定的秒数或毫秒数
Instant minusSecondsInstant = now.minusSeconds(1800);
Instant minusMillisInstant = now.minusMillis(500);
System.out.println("减去30分钟后的时间:" + minusSecondsInstant);
System.out.println("减去0.5秒后的时间:" + minusMillisInstant);

// 比较两个时间戳的先后顺序
Instant earlierInstant = Instant.parse("2023-08-14T09:00:00Z");
Instant laterInstant = Instant.parse("2023-08-14T11:00:00Z");
boolean isBefore = earlierInstant.isBefore(laterInstant);
boolean isAfter = earlierInstant.isAfter(laterInstant);
System.out.println("earlierInstant是否在laterInstant之前:" + isBefore);
System.out.println("earlierInstant是否在laterInstant之后:" + isAfter);
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
当前时间:2023-10-25T05:09:44.739476300Z
当前时间(使用指定时钟):2023-10-25T05:09:44.743463Z
197011日起的秒数对应的时间:2009-02-13T23:31:30Z
197011日起的毫秒数对应的时间:2021-07-27T06:40:00Z
时间戳的秒数部分:1698210584
时间戳的纳秒数部分:739476300
解析后的时间:2023-08-14T10:30:00Z
增加1小时后的时间:2023-10-25T06:09:44.739476300Z
增加1秒后的时间:2023-10-25T05:09:45.739476300Z
减去30分钟后的时间:2023-10-25T04:39:44.739476300Z
减去0.5秒后的时间:2023-10-25T05:09:44.239476300Z
earlierInstant是否在laterInstant之前:true
earlierInstant是否在laterInstant之后:false

LocalData(日期)类

LocalData类是Java 8引入的日期类,用于表示日期(年、月、日)信息。该类具有以下方法:

常用方法:

  • now():这是一个静态方法,返回表示当前日期的LocalDate对象。例如,LocalDate.now()将返回表示今天日期的对象。
  • of(int year, int month, int dayOfMonth):这是另一个静态方法,通过指定年、月、日创建LocalDate对象。参数year表示年份,month表示月份(1到12之间),dayOfMonth表示月份中的某一天。
  • format(DateTimeFormatter formatter):该方法可将LocalDate对象按照指定的格式转换为字符串表示。需要传入一个DateTimeFormatter对象,可以使用预定义的格式或自定义格式。例如,date.format(DateTimeFormatter.ofPattern(“yyyy-MM-dd”))将返回带有“年-月-日”格式的日期字符串。
  • plusYears(long years) / minusYears(long years):这些方法用于在现有的LocalDate对象上增加或减少指定的年数。参数years表示要增加或减少的年数。
  • plusMonths(long months) / minusMonths(long months):与上述方法类似,这些方法用于在现有的LocalDate对象上增加或减少指定的月数。
  • plusDays(long days) / minusDays(long days):这些方法用于在现有的LocalDate对象上增加或减少指定的天数。
  • isBefore(LocalDate other) / isAfter(LocalDate other):这两个方法用于比较两个LocalDate对象的先后顺序。isBefore()方法返回一个布尔值,表示该日期是否在参数日期之前;isAfter()方法返回一个布尔值,表示该日期是否在参数日期之后。
  • getYear() / getMonthValue() / getDayOfMonth():这些方法用于获取LocalDate对象的年、月、日信息。
  • isLeapYear():用于判断指定年份是否为闰年。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class Test {
public static void main(String[] args) {
// 获取当前日期
LocalDate currentDate = LocalDate.now();
System.out.println("当前日期:" + currentDate);

// 创建指定日期
LocalDate customDate = LocalDate.of(2023, 8, 14);
System.out.println("自定义日期:" + customDate);

// 格式化日期为字符串
String formattedDate = customDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println("格式化后的日期:" + formattedDate);

// 增减年份
LocalDate futureDate = customDate.plusYears(2);
System.out.println("增加两年后的日期:" + futureDate);

// 判断日期先后
boolean isBefore = customDate.isBefore(currentDate);
boolean isAfter = customDate.isAfter(currentDate);
System.out.println("自定义日期是否在当前日期之前:" + isBefore);
System.out.println("自定义日期是否在当前日期之后:" + isAfter);

// 获取年、月、日
int year = customDate.getYear();
int month = customDate.getMonthValue();
int dayOfMonth = customDate.getDayOfMonth();
System.out.println("年:" + year);
System.out.println("月:" + month);
System.out.println("日:" + dayOfMonth);

// 判断闰年
boolean isLeapYear = customDate.isLeapYear();
System.out.println("自定义日期所在年份是否为闰年:" + isLeapYear);
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
当前日期:2023-10-25
自定义日期:2023-08-14
格式化后的日期:2023-08-14
增加两年后的日期:2025-08-14
自定义日期是否在当前日期之前:true
自定义日期是否在当前日期之后:false
年:2023
月:8
日:14
自定义日期所在年份是否为闰年:false

LocalTime(时间)类

LocalTime类用来表示时间,通常表示的是小时分钟秒。与LocalData类一样,该类不能代表时间线上的即时信息,只是时间的描述。在LocalTime类中提供了获取时间对象的方法,与LocalData用法类似。

同时LocalTime类也提供了与日期类相对应的时间格式化、增减时分秒等常用方法,这些方法与LocalData(日期)类相对应,这里我们不再详细列举。


示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Test {
public static void main(String[] args) {
// 获取当前时间
LocalTime currentTime = LocalTime.now();
System.out.println("当前时间:" + currentTime);

// 创建指定时间
LocalTime customTime = LocalTime.of(12, 30, 45);
System.out.println("自定义时间:" + customTime);

// 格式化时间为字符串
String formattedTime = customTime.format(DateTimeFormatter.ofPattern("HH:mm:ss"));
System.out.println("格式化后的时间:" + formattedTime);

// 增减小时数
LocalTime futureTime = customTime.plusHours(2);
System.out.println("增加两小时后的时间:" + futureTime);

// 判断时间先后
boolean isBefore = customTime.isBefore(currentTime);
boolean isAfter = customTime.isAfter(currentTime);
System.out.println("自定义时间是否在当前时间之前:" + isBefore);
System.out.println("自定义时间是否在当前时间之后:" + isAfter);

// 获取小时、分钟、秒
int hour = customTime.getHour();
int minute = customTime.getMinute();
int second = customTime.getSecond();
System.out.println("小时:" + hour);
System.out.println("分钟:" + minute);
System.out.println("秒:" + second);
}
}

运行结果:

1
2
3
4
5
6
7
8
9
当前时间:13:13:29.649140600
自定义时间:12:30:45
格式化后的时间:12:30:45
增加两小时后的时间:14:30:45
自定义时间是否在当前时间之前:true
自定义时间是否在当前时间之后:false
小时:12
分钟:30
秒:45

LocalDataTime(日期时间)类

LocalDataTime类是日期(LocalDate)类与时间(LocalTime)类的综合,它即包含日期也包含时间,通过查看API可以知道,LocalDataTime类中的方法包含了LocalData类与LocalTime类的方法。

需要注意的是,LocalDateTime默认的格式是 2020-02-29T21:23:26.774,这可能与我们经常使用的格式不太符合,所以它经常和DateTimeFormatter一起使用指定格式,除了LocalData与LocalTime类中的方法,额外提供了转换的方法。

常用方法:

以下是一些LocalDateTime类常用的方法:

  • now():静态方法,返回当前日期和时间的LocalDateTime对象。
  • of(int year, int month, int dayOfMonth, int hour, int minute) / of(int year, int month, int dayOfMonth, int hour, int minute, int second):静态方法,通过指定年、月、日、小时、分钟以及秒数(可选)创建LocalDateTime对象。
  • parse(CharSequence text):静态方法,将字符串解析为LocalDateTime对象。
  • format(DateTimeFormatter formatter):将LocalDateTime对象按照指定格式转换为字符串表示。
  • toLocalDate():获取LocalDateTime对象的日期部分,返回LocalDate对象。
  • toLocalTime():获取LocalDateTime对象的时间部分,返回LocalTime对象。
  • plusYears(long years) / minusYears(long years):在现有的LocalDateTime对象上增加或减少指定年数。
  • plusMonths(long months) / minusMonths(long months):在现有的LocalDateTime对象上增加或减少指定月数。
  • plusDays(long days) / minusDays(long days):在现有的LocalDateTime对象上增加或减少指定天数。
  • plusHours(long hours) / minusHours(long hours):在现有的LocalDateTime对象上增加或减少指定小时数。
  • plusMinutes(long minutes) / minusMinutes(long minutes):在现有的LocalDateTime对象上增加或减少指定分钟数。
  • plusSeconds(long seconds) / minusSeconds(long seconds):在现有的LocalDateTime对象上增加或减少指定秒数。
  • getYear() / getMonthValue() / getDayOfMonth():获取LocalDateTime对象的年、月、日信息。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;

public class Test {
public static void main(String[] args) {
// 获取当前日期和时间
LocalDateTime currentDateTime = LocalDateTime.now();
System.out.println("当前日期和时间:" + currentDateTime);

// 创建指定的日期和时间
LocalDateTime customDateTime = LocalDateTime.of(2023, 10, 24, 12, 30);
System.out.println("自定义日期和时间:" + customDateTime);

// 格式化日期时间为字符串
String formattedDateTime = customDateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println("格式化后的日期和时间:" + formattedDateTime);

// 增减年数、月数、天数、小时数、分钟数、秒数
LocalDateTime futureDateTime = customDateTime.plusYears(1).minusMonths(2).plusDays(15).minusHours(3).plusMinutes(10).plusSeconds(30);
System.out.println("操作后的日期和时间:" + futureDateTime);

// 获取日期和时间部分
LocalDate datePart = customDateTime.toLocalDate();
LocalTime timePart = customDateTime.toLocalTime();
System.out.println("日期部分:" + datePart);
System.out.println("时间部分:" + timePart);

// 获取年、月、日信息
int year = customDateTime.getYear();
int month = customDateTime.getMonthValue();
int dayOfMonth = customDateTime.getDayOfMonth();
System.out.println("年:" + year);
System.out.println("月:" + month);
System.out.println("日:" + dayOfMonth);
}
}

运行结果:

1
2
3
4
5
6
7
8
9
当前日期和时间:2023-10-25T13:19:39.667325400
自定义日期和时间:2023-10-24T12:30
格式化后的日期和时间:2023-10-24 12:30:00
操作后的日期和时间:2024-09-08T09:40:30
日期部分:2023-10-24
时间部分:12:30
年:2023
月:10
日:24

Duration(时间间隔)类

Duration类是Java 8引入的一个用于表示时间间隔的类。它可用于计算两个时间点之间的差异,以及在不同单位(如秒、分钟、小时等)之间进行转换。

常用方法:

以下是一些Duration类常用的方法:

  • ofDays(long days) / ofHours(long hours) / ofMinutes(long minutes):静态方法,创建一个持续时间,表示指定的天数、小时数或分钟数。
  • ofSeconds(long seconds) / ofMillis(long milliseconds) / ofNanos(long nanos):静态方法,创建一个持续时间,表示指定的秒数、毫秒数或纳秒数。
  • between(Temporal startInclusive, Temporal endExclusive):静态方法,创建一个持续时间,表示从起始时间到结束时间之间的差异。
  • plus(Duration duration) / minus(Duration duration):在现有的Duration对象上增加或减少另一个Duration对象的持续时间。
  • toDays() / toHours() / toMinutes():将持续时间转换为对应的天数、小时数或分钟数。
  • toSeconds() / toMillis() / toNanos():将持续时间转换为对应的秒数、毫秒数或纳秒数。
  • getSeconds() / getNano():获取持续时间中的秒数和纳秒数。
  • isNegative() / isZero():判断持续时间是否为负值或零值。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import java.time.Duration;

public class Test {
public static void main(String[] args) {
// 创建一个持续时间,表示5小时30分钟15秒
Duration duration1 = Duration.ofHours(5).plusMinutes(30).plusSeconds(15);
System.out.println("Duration 1: " + duration1); // 输出:PT5H30M15S

// 创建一个持续时间,表示1分钟
Duration duration2 = Duration.ofMinutes(1);
System.out.println("Duration 2: " + duration2); // 输出:PT1M

// 计算两个持续时间之间的差异
Duration difference = duration1.minus(duration2);
System.out.println("Difference: " + difference); // 输出:PT5H29M15S

// 获取持续时间的小时数、分钟数和秒数
long hours = difference.toHours();
long minutes = difference.toMinutesPart();
long seconds = difference.toSecondsPart();
System.out.println("Hours: " + hours); // 输出:5
System.out.println("Minutes: " + minutes); // 输出:29
System.out.println("Seconds: " + seconds); // 输出:15

// 判断持续时间是否为负值或零值
boolean isNegative = difference.isNegative();
boolean isZero = difference.isZero();
System.out.println("是负的? " + isNegative); // 输出:false
System.out.println("是零吗? " + isZero); // 输出:false
}
}

运行结果:

1
2
3
4
5
6
7
8
Duration 1: PT5H30M15S
Duration 2: PT1M
Difference: PT5H29M15S
Hours: 5
Minutes: 29
Seconds: 15
是负的? false
是零吗? false

Period(日期间隔)类

Period主要用于计算两个日期的间隔,与Duration相同,也是通过between计算日期间隔,并提供了获取年月日的三个常用方法,分别是 getYears()、getMonths()和getDays()。


示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import java.time.LocalDate;
import java.time.Period;

public class Test {
public static void main(String[] args) {
// 创建两个日期
LocalDate startDate = LocalDate.of(2023, 1, 1);
LocalDate endDate = LocalDate.of(2023, 4, 30);

// 计算日期之间的差异
Period period = Period.between(startDate, endDate);
System.out.println("日期间隔: " + period); // 输出:P3M29D

// 获取年、月、日的差异
int years = period.getYears();
int months = period.getMonths();
int days = period.getDays();
System.out.println("年: " + years); // 输出:0
System.out.println("月: " + months); // 输出:3
System.out.println("日: " + days); // 输出:29

// 添加日期间隔到指定日期
LocalDate newDate = startDate.plus(period);
System.out.println("新日期: " + newDate); // 输出:2023-04-30

// 判断日期间隔是否为负值或零值
boolean isNegative = period.isNegative();
boolean isZero = period.isZero();
System.out.println("是否为负值? " + isNegative); // 输出:false
System.out.println("是否为零值? " + isZero); // 输出:false
}
}

运行结果:

1
2
3
4
5
6
7
日期间隔: P3M29D
年: 0
月: 3
日: 29
新日期: 2023-04-30
是否为负值? false
是否为零值? false

Clock(获取时区)类

Clock类是Java中用于获取当前时间、日期和时区信息的抽象类。它提供了一种通用的方式来访问系统时钟,并以不同的时区获取当前时间。

常用方法:

  • systemDefaultZone():静态方法,返回使用系统默认时区的系统时钟。
  • systemUTC():静态方法,返回使用协调世界时(UTC)的系统时钟。
  • tick(Clock fixedClock, Duration tickDuration):静态方法,返回一个包装了指定时钟的”滴答”时钟,每次前进指定的时长。
  • fixed(Instant fixedInstant, ZoneId zone):静态方法,返回一个固定的时钟,始终返回指定的瞬间和时区。
  • offset(Clock baseClock, Duration offsetDuration):静态方法,返回一个相对于基准时钟偏移指定持续时间的时钟。
  • millis():实例方法,返回从1970年1月1日午夜开始的毫秒数。
  • instant():实例方法,返回当前时钟的当前瞬间。
  • getZone():实例方法,返回时钟的时区信息。

示例代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import java.time.Clock;
import java.time.Duration;
import java.time.Instant;
import java.time.ZoneId;

public class Test {
public static void main(String[] args) {
// 获取系统默认时区的时钟
Clock systemDefaultClock = Clock.systemDefaultZone();
System.out.println("系统默认时钟:" + systemDefaultClock);

// 获取使用协调世界时(UTC)的系统时钟
Clock systemUTCClock = Clock.systemUTC();
System.out.println("系统UTC时钟:" + systemUTCClock);

// 创建一个滴答时钟,每次前进1秒钟
Clock tickClock = Clock.tick(systemDefaultClock, Duration.ofSeconds(1));
System.out.println("滴答时钟:" + tickClock);

// 创建一个固定的时钟,始终返回指定的瞬间和时区
Instant fixedInstant = Instant.parse("2022-01-01T00:00:00Z");
ZoneId fixedZone = ZoneId.of("Asia/Shanghai");//亚洲/上海
Clock fixedClock = Clock.fixed(fixedInstant, fixedZone);
System.out.println("固定时钟:" + fixedClock);

// 创建一个相对于基准时钟偏移10秒钟的时钟
Clock baseClock = Clock.systemDefaultZone();
Duration offsetDuration = Duration.ofSeconds(10);
Clock offsetClock = Clock.offset(baseClock, offsetDuration);
System.out.println("偏移时钟:" + offsetClock);

// 获取当前时钟的毫秒数
long millis = systemDefaultClock.millis();
System.out.println("毫秒数:" + millis);

// 获取当前时钟的当前瞬间
Instant instant = systemDefaultClock.instant();
System.out.println("当前瞬间:" + instant);

// 获取当前时钟的时区信息
ZoneId zone = systemDefaultClock.getZone();
System.out.println("时区:" + zone);
}
}

运行结果:

1
2
3
4
5
6
7
8
系统默认时钟:SystemClock[Asia/Shanghai]
系统UTC时钟:SystemClock[Z]
滴答时钟:TickClock[SystemClock[Asia/Shanghai],PT1S]
固定时钟:FixedClock[2022-01-01T00:00:00Z,Asia/Shanghai]
偏移时钟:OffsetClock[SystemClock[Asia/Shanghai],PT10S]
毫秒数:1698211710976
当前瞬间:2023-10-25T05:28:30.976562Z
时区:Asia/Shanghai