导言
Java 8 引入了一套全新的时间日期API,这些API在java.time
包下,它们解决了旧版java.util.Date
类和java.util.Calendar
类的线程安全问题,并提供了更为丰富和灵活的功能。以下是Java 8中时间日期处理的关键类:
-
LocalDate
:表示没有时间和时区的日期,如2024-01-08。 -
LocalTime
:表示没有日期和时区的时间,如10:15:30。 -
LocalDateTime
:表示没有时区的日期和时间,结合了LocalDate
和LocalTime
,如2024-01-08T10:15:30。 -
ZonedDateTime
:表示带时区的日期和时间,它是在LocalDateTime
的基础上加上了时区信息。 -
Instant
:表示时间线上的一个瞬时点,通常用于生成时间戳。 -
Duration
:表示两个时间之间的时长,用于计算两个LocalTime
、两个Instant
或两个LocalDateTime
之间的差异。 -
Period
:表示两个日期之间的时长,用于计算两个LocalDate
之间的差异。 -
DateTimeFormatter
:用于日期时间的格式化和解析。 -
Clock
:提供对当前日期和时间的访问,可以用于替代System.currentTimeMillis()
和TimeZone.getDefault()
。
这些类都是不可变且线程安全的,可以通过其提供的各种工厂方法来创建实例,也提供了丰富的方法用于日期时间的计算、解析和格式化。例如:
// 获取当前日期
LocalDate today = LocalDate.now();
// 创建一个日期
LocalDate someDate = LocalDate.of(2024, Month.JANUARY, 8);
// 在现有日期的基础上增加天数
LocalDate tomorrow = today.plusDays(1);
// 解析日期字符串
LocalDate anotherDate = LocalDate.parse("2024-01-08");
// 格式化日期
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
String formattedDate = today.format(formatter);
// 获取当前时间戳
Instant now = Instant.now();
// 日期时间的计算
Duration duration = Duration.between(startTime, endTime);
Period period = Period.between(startDate, endDate);
Java 8的这套时间日期API大大简化了时间日期的处理,并且让代码更加清晰易读。
一、类型转换
常用的是java.util.Date和java.time.LocalDate之间的转换
,而要在java.util.Date
和Java 8中的java.time.LocalDate
之间进行转换,你需要考虑到Date
是带有时间和时区的,而LocalDate
仅包含日期信息,没有时间和时区的概念。下面是如何在两者之间进行转换的方法:
1.Date 转换为 LocalDate
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
Date date = new Date();
LocalDate localDate = date.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
在这里,我们首先将Date
对象转换为Instant
,然后将Instant
与系统默认时区结合以创建ZonedDateTime
对象,最后我们调用toLocalDate
方法来获取LocalDate
对象。
2.LocalDate 转换为 Date
import java.time.LocalDate;
import java.time.ZoneId;
import java.util.Date;
LocalDate localDate = LocalDate.now();
Date date = Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
这里,我们首先将LocalDate
转换为当天开始时的LocalDateTime
,然后将其与系统默认时区结合,创建一个ZonedDateTime
对象。最后,我们通过调用toInstant
方法并传递该瞬时值给Date.from
方法来创建一个Date
对象。
需要注意的是,在转换过程中,由于LocalDate
不包含时间信息,所以默认转换为Date
时会将时间设置为午夜开始(00:00:00)。同样,由于Date
包含时区信息,而LocalDate
不包含,所以必须指定一个时区来进行准确的转换,通常使用系统默认时区ZoneId.systemDefault()
。如果你需要处理其他时区,可以替换为对应的ZoneId
。
二、日期格式化
在Java中,时间格式化通常是指将日期时间对象转换为特定格式的字符串。Java提供了DateTimeFormatter
类来进行日期时间的格式化。以下是一些常用的时间格式化模式:
1.ISO 标准格式:
DateTimeFormatter.ISO_LOCAL_DATE
:2024-01-08
DateTimeFormatter.ISO_LOCAL_TIME
:11:56:15
DateTimeFormatter.ISO_LOCAL_DATE_TIME
:2024-01-08T11:56:15
DateTimeFormatter.ISO_OFFSET_DATE_TIME
:2024-01-08T11:56:15+01:00
DateTimeFormatter.ISO_ZONED_DATE_TIME
:2024-01-08T11:56:15+01:00[Europe/Paris]
2.自定义格式:
yyyy-MM-dd
:2024-01-08
(年-月-日)dd/MM/yyyy
:08/01/2024
(日/月/年)MM-dd-yyyy HH:mm
:01-08-2024 11:56
(月-日-年 时:分)EEEE, MMMM dd, yyyy
:Tuesday, January 08, 2024
(星期, 月份 日, 年)hh:mm a
:11:56 AM
(时:分 上午/下午)HH:mm:ss
:11:56:15
(时:分:秒)yyyy-MM-dd'T'HH:mm:ss.SSSXXX
:2024-01-08T11:56:15.000Z
(年-月-日T时:分:秒.毫秒时区)
3.DateTimeFormatter
使用DateTimeFormatter
进行格式化,可以使用其静态方法ofPattern
创建一个格式化器,然后调用日期时间对象的format
方法。例如:
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
LocalDateTime now = LocalDateTime.now();
// 使用自定义格式化
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
String formatted = now.format(formatter);
System.out.println(formatted);
也可以直接使用预定义的格式化器,例如:
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
LocalDate today = LocalDate.now();
// 使用预定义的ISO_LOCAL_DATE格式化器
String formatted = today.format(DateTimeFormatter.ISO_LOCAL_DATE);
System.out.println(formatted);
4.Date
对于java.util.Date
对象,需要使用SimpleDateFormat
类来格式化日期。
import java.text.SimpleDateFormat;
import java.util.Date;
Date date = new Date();
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String formattedDate = formatter.format(date);
System.out.println(formattedDate);
5.LocalDate
对于java.time.LocalDate
对象,应该使用DateTimeFormatter
类来格式化日期。
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
LocalDate localDate = LocalDate.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
String formattedDate = localDate.format(formatter);
System.out.println(formattedDate);
注意事项
- 当使用
SimpleDateFormat
时,请注意它不是线程安全的,所以如果在多线程环境中,每个线程应该有自己的SimpleDateFormat
实例或者使用同步机制。 DateTimeFormatter
是不可变的和线程安全的,所以它可以被多个线程共享使用。- 格式化模式字符串(如
"yyyy-MM-dd HH:mm:ss"
)是大小写敏感的,所以MM
代表月份,而mm
代表分钟,yyyy
代表四位年份,而yy
代表两位年份。