目录
Java 8
推出了整套的日期时间 API
,有了这套 API
就可以放弃所有的 java.util.Date
、java.sql.Date
、Timestamp
、Calendar
等,也不用再担心 SimpleDateFormat
的线程安全问题,同时还提供了更好用的日期处理方法。接下来就开始学习一下这套 API
的使用
类名 | 描述 |
---|---|
LocalDate | 只包含日期,如:2000-01-01 |
LocalTime | 只包含时间,如:14:02:10 |
LocalDateTime | 包含日期和时间,如:2000-01-01 14:02:10 |
Instant | 时间戳 |
Period | 时间段 |
Duration | 时间差 |
ZoneOffset | 时区偏移量,如:+8:00 |
ZonedDateTime | 带时区的时间 |
Clock | 时钟 |
获取当前日期时间
- 获取当天日期
public static LocalDate today() {
return LocalDate.now();
}
- 获取当前时间
public static LocalTime nowTime() {
return LocalTime.now();
}
- 获取当前日期 + 时间
public static LocalDateTime now() {
return LocalDateTime.now();
}
获取指定日期时间
- 获取指定日期
public static LocalDate ofDate(int year, int month, int day) {
return LocalDate.of(year, month, day);
}
- 获取指定时间
public static LocalTime ofTime(int hour, int minute, int second) {
return LocalTime.of(hour, minute, second);
}
- 获取指定日期 + 时间
public static LocalDateTime ofDateTime(int year, int month, int day, int hour, int minute, int second) {
return LocalDateTime.of(year, month, day, hour, minute, second);
}
public static LocalDateTime ofDateTime(LocalDate date, LocalTime time) {
return LocalDateTime.of(date, time);
}
日期比较
- 是否相等
可以使用 equals
方法,也可以使用 isEqual
方法,isEqual
方法如果比较的日期为空,则会抛出异常
public static boolean equals(LocalDate date1, LocalDate date2) {
return date1 != null && date1.equals(date2);
}
public static boolean equals(LocalDate date1, LocalDate date2) {
return date1 != null && date2 != null && date1.isEqual(date2);
}
- 比较大小
public static void main(String[] args) {
LocalDateTime d1 = LocalDate.of(2021, 8, 10).atStartOfDay();
LocalDateTime d2 = LocalDateTime.of(2021, 8, 10, 12, 0);
System.out.println(d1.isAfter(d2));
System.out.println(d1.isBefore(d2));
}
日期格式化
通过 DateTimeFormatter
设置格式
- 日期转换为字符串
public static String format(LocalDate date, String pattern) {
return date == null ? "" : date.format(DateTimeFormatter.ofPattern(pattern));
}
public static String format(LocalTime date, String pattern) {
return date == null ? "" : date.format(DateTimeFormatter.ofPattern(pattern));
}
public static String format(LocalDateTime date, String pattern) {
return date == null ? "" : date.format(DateTimeFormatter.ofPattern(pattern));
}
- 字符串转换为日期
public static LocalDate parseDate(String date, String pattern) {
return LocalDate.parse(date, DateTimeFormatter.ofPattern(pattern));
}
public static LocalTime parseTime(String date, String pattern) {
return LocalTime.parse(date, DateTimeFormatter.ofPattern(pattern));
}
public static LocalDateTime parseDateTime(String date, String pattern) {
return LocalDateTime.parse(date, DateTimeFormatter.ofPattern(pattern));
}
获取当前时间戳
通过 Instant
类来处理时间戳,这个方法相当于 System.currentTimeMillis()
public static long currentTimeMillis() {
return Instant.now().toEpochMilli();
}
日期通过转换为 Instant
,就可以获取其时间戳,这里的转换默认使用了 东8区
时区
public static Instant toInstant(LocalDate date) {
return date == null ? null : toInstant(date.atStartOfDay());
}
public static Instant toInstant(LocalDateTime date) {
return toInstant(date, ZoneOffset.ofHours(8));
}
public static Instant toInstant(LocalDateTime date, ZoneOffset zoneOffset) {
return date == null ? null : date.toInstant(zoneOffset);
}
public static Instant toInstant(Date date) {
return date == null ? null : date.toInstant();
}
通过时间戳生成当前时间
public static LocalDateTime toLocalDateTime(Long timestamp) {
if (timestamp == null) {
return null;
}
return Instant.ofEpochMilli(timestamp).atZone(ZoneOffset.ofHours(8)).toLocalDateTime();
}
获取当天开始时间
public static LocalDateTime atStartOfDay(LocalDateTime date) {
return date == null ? null : date.toLocalDate().atStartOfDay();
}
获取当天结束时间
public static LocalDateTime atLastOfDay(LocalDateTime date) {
return date == null ? null : date.toLocalDate().atStartOfDay().plusDays(1).minusSeconds(1);
}
日期操作函数
Java8
提供了非常方便的日期操作方法,plus
开头的方法是日期加方法,minus
开头的方法是日期减方法。
单位 | 日期加 | 日期减 |
---|---|---|
年 | plusYears | minusYears |
月 | plusMonths | minusMonths |
星期 | plusWeeks | minusWeeks |
天 | plusDays | minusDays |
小时 | plusHours | minusHours |
分钟 | plusMinutes | minusMinutes |
秒 | plusSeconds | minusSeconds |
纳秒 | plusNanos | minusNanos |
示例:当前时间向后增加一年,再减去一天
public static void main(String[] args) {
LocalDateTime now = LocalDateTime.now();
now.plusYears(1).minusDays(1);
}
计算两个日期之间相差的天数
Duration
不支持 LocalDate
,可以把 LocalDate
转换为 LocalDateTime
使用,计算的是两个时间点之间相差的秒数,然后根据不同的方法转换为不同的单位,Duration
提供了 toDays
, toHours
,toMinutes
等方法。
public static long diffDays(LocalDate d1, LocalDate d2) {
return Math.abs(d1.toEpochDay() - d2.toEpochDay());
}
public static long diffDays(LocalDateTime d1, LocalDateTime d2) {
Duration between = Duration.between(d1, d2);
return Math.abs(between.toDays());
}
通过 Period
也可以计算相差的天数,但 Period
会把相差的日期使用 年-月-日
三个单位进行存储。
public static void main(String[] args) {
Period between = Period.between(today(), today().plusYears(1).plusDays(10));
System.out.println(between.getYears());
System.out.println(between.getMonths());
System.out.println(between.getDays());
}
输出结果为
1
0
10
判断是否生日这种周期性日期
public static boolean isBirthday(LocalDate date, Integer month, Integer day) {
return date != null && month != null && day != null && MonthDay.of(month, day).equals(MonthDay.from(date));
}
获取一个月有多少天
public static Integer getMonthDay(TemporalAccessor date) {
return date == null ? null : YearMonth.from(date).lengthOfMonth();
}
获取时钟
Clock
时钟类用于获取当前时间戳
public static void main(String[] args) {
Clock defaultClock = Clock.systemDefaultZone();
System.out.println(defaultClock.getZone().getId());
Clock utcClock = Clock.systemUTC();
System.out.println(utcClock.getZone().getId());
Clock djClock = Clock.system(ZoneOffset.ofHours(9));
System.out.println(djClock.getZone().getId());
System.out.println("Clock : " + defaultClock.millis());
}