java.util.Date
类允许创建和操纵表示特定瞬间的时间对象。java.time.LocalDate
和 java.time.LocalDateTime
类允许操作日期和时间,但不考虑时区。java.time.ZonedDateTime
类允许操作日期和时间,同时考虑到时区的影响。java.time.Duration
类允许计算两个时刻之间的持续时间。java.time.Period
类允许计算两个日期之间的期间。java.time.format.DateTimeFormatter
类允许将日期和时间格式化为人类可读的形式。1.不可变性:LocalDateTime
是不可变
的类型,一旦创建后,其值是不可变的。而Date
是可变
的类型,可以通过方法修改其值。
2.线程安全性:LocalDateTime
是线程安全
的,多个线程可以同时访问和操作不同的LocalDateTime实例。而Date
是非线程安全
的,如果多个线程同时访问和修改同一个Date实例,可能会导致不可预期的结果。
3.时间精度:LocalDateTime
提供了纳秒
级别的时间精度
,可以表示更加精确的时间。而Date
只能表示毫秒
级别的时间精度
。
4.时区处理:LocalDateTime
默认不包含时区信息
,表示的是本地日期和时间
。而Date
则包含时区信息
,它的实际值会受到系统默认时区的影响。
在 Java 中,LocalDateTime
是不可变的,而 Date
是可变的。这意味着一旦创建了一个 LocalDateTime
对象,就不能更改其值。相比之下,可以更改 Date
对象的值。
以下是一个示例,说明 LocalDateTime
是不可变的:
LocalDateTime ldt = LocalDateTime.now();
ldt.withHour(2); // 这个方法会返回一个新的 LocalDateTime 对象,而不会更改原来的对象
在这个例子中,withHour(int hour)
方法返回一个新的 LocalDateTime
对象,其中小时设置为 2。然而,原始的 LocalDateTime
对象并没有改变。
相反,对于 Date
对象来说,可以直接更改其值:
Date date = new Date();
date.setYear(2023); // 这个方法会更改原有的 Date 对象
在这个例子中,setYear(int year)
方法会更改原始的 Date
对象,使其变为2023年。
LocalDate不可变类时间对象优点:
通过LocalDateTime的atZone()方法和Date的toInstant()方法进行转换。
在 Java 中,您可以使用 LocalDateTime
的 atZone()
方法和 Date
的 toInstant()
方法来将 LocalDateTime
对象转换为 Date
对象,反之亦然。以下是一些示例:
将 LocalDateTime
转换为 Date
:
// 创建一个 LocalDatetime 对象
LocalDateTime ldt = LocalDateTime.of(2023, Month.JANUARY, 1, 10, 30);
// 使用 atZone() 方法将其转换为 ZonedDateTime
ZonedDateTime zdt = ldt.atZone(ZoneId.of("UTC"));
// 将 ZonedDateTime 转换为 Instant
Instant instant = zdt.toInstant();
// 将 Instant 转换为 Date
Date date = Date.from(instant);
将 Date
转换为 LocalDateTime
:
// 创建一个 Date 对象
Date date = new Date();
// 将 Date 转换为 Instant
Instant instant = date.toInstant();
// 将 Instant 转换为 ZonedDateTime
ZonedDateTime zdt = instant.atZone(ZoneId.of("UTC"));
// 将 ZonedDateTime 转换为 LocalDateTime
LocalDateTime ldt = zdt.toLocalDateTime();
请注意,在进行此类转换时,必须指定一个时区。否则,无法确定 LocalDateTime
的确切时间点。在上述示例中,我们使用 “UTC” 作为时区。如果您想使用其他时区,请替换 ZoneId.of("UTC")
中的 “UTC”。
在 Java 中,可以使用 LocalDateTime 对象进行日期和时间的相减操作。由于它们都是数值对象,所以可以直接相减得到时间差值。另外,它们还具有 equals() 和 compareTo() 方法,可以比较两个 LocalDateTime 对象是否相同或一个比另一个大。
下面是一个简单的示例:
LocalDateTime start = LocalDateTime.now();
Thread.sleep(5000); // 约等于 5 秒延迟
LocalDateTime end = LocalDateTime.now();
Duration duration = Duration.between(start,end);
long seconds = duration.getSeconds();
在这个示例中,Duration.between()
方法会返回两个 LocalDateTime 对象之间的持续时间。这将会得到一个 Duration 对象,其中包含了毫秒数,可以进一步提取出秒数。如果你想知道整分钟或整小时的数量,请用 seconds 或 minutes 方法,分别是 duration.getSeconds()
和 duration.toMinutes()
。请注意,Duration 的 API 也可用来提取其他时间单位,如分钟、小时和天数等。
请注意,由于 LocalDateTime 不包含时区信息,在比较时间时最好确保时区一致,否则会出现错误。如果你需要考虑时区,请使用 ZonedDateTime 对象。
ZonedDateTime zstart = ZonedDateTime.now(); // 代表本地时区
Thread.sleep(5000);
ZonedDateTime zend = ZonedDateTime.now();
Duration duration = Duration.between(zstart, zend);
long seconds = duration.getSeconds();
上述代码就可以得到相差的时间,以秒为单位。你还可以使用 Duration 来获取其他时间单位,例如Duration常用方法:
Duration
类是 Java 时间日期包中的一个类,表示一个时间段。以下是一些常用的 Duration
类方法:
Duration d = Duration.between(date1, date2);
Duration
对象转为天数long days = d.toDays();
Duration
对象转为小时数long hours = d.toHours();
Duration
对象转为分钟数long minutes = d.toMinutes();
Duration
对象转为秒数long seconds = d.getSeconds();
Duration
对象转为毫秒数long millis = d.toMillis();
Duration
对象,使得对象值增加相应的时间长度d.plus(amountToAdd);
Duration
对象中减去一个值,使得对象值减少相应的时间长度d.minus(amountToSubtract);
Duration
对象,它的值等于原对象的绝对值Duration absolute = d.abs();
Duration 类处理 Date 类型的对象。可以先将 Date 对象转化为 LocalDateTime 对象,然后再进行减法操作:
// 创建两个 Date 对象
Date date1 = new Date();
Thread.sleep(5 * 1000); // 约等于五秒钟延迟
Date date2 = new Date();
// 转换为 LocalDateTime 对象
LocalDateTime ldt1 = date1.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
LocalDateTime ldt2 = date2.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
// 计算时间差
Duration d = Duration.between(ldt1, ldt2);
// 打印结果
System.out.println(d.getSeconds()); // 输出大约等于 5 的结果
上述代码将计算两个 Date 对象之间的持续时间,并打印出来。如果你想知道整分钟或整小时的数量,请用 seconds 或 minutes 方法,分别是 d.getSeconds()
和 d.toMinutes()
。
在Java中,可以使用LocalDateTime重写
的Object
类的compareTo()
方法进行LocalDateTime对象之间的时间比较
。该方法返回一个整数值(正整数、零或负整数)来表示比较结果。
import java.time.LocalDateTime;
public class LocalDateTimeCompare {
public static void main(String[] args) {
LocalDateTime dateTime1 = LocalDateTime.of(2023, 6, 7, 10, 30);
LocalDateTime dateTime2 = LocalDateTime.of(2023, 6, 8, 10, 30);
int result = dateTime1.compareTo(dateTime2);
if (result < 0) {
//负整数调用时间小
System.out.println("dateTime1 is before dateTime2");
} else if (result > 0) {
//正整数调用时间大
System.out.println("dateTime1 is after dateTime2");
} else {
//0两个时间相等
System.out.println("dateTime1 is equal to dateTime2");
}
}
}
LocalDateTime now = LocalDateTime.now();
//String类型格式化后的时间
String format = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(now);
//LocalDateTime类型格式化后的时间
LocalDateTime formatted = LocalDateTime.parse(format, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(formatted);
SimpleDateFormat线程不安全,DateTimeFormatter线程安全。
SimpleDateFormat 类更适合处理 Date 类型,DateTimeFormatter更适合处理LocalDateTime或LocalDate,但是其也可以间接格式化Date。
个人建议使用LocalDate和LocalDateTime比较方便和安全。
DateTimeFormatter
类主要处理的是TemporalAccessor
对象,包括LocalDateTime
,
LocalDate
,LocalTime
,YearMonth
,MonthDay
和OffsetDateTime
类型。不过也可以间接格式化Date
对象。请参考以下代码示例:Date date = new Date(); TemporalAccessor temporal = TemporalAccessor.from(date.toInstant()); String format = DateTimeFormatter.ISO_LOCAL_DATE.format(temporal); System.out.println(format);
上述代码中
TemporalAccessor
接口可以接收Date
对象,并且把它们转换成LocalDateTime
对象,然后再使用DateTimeFormatter
格式化它。请注意,TemporalAccessor
还有其他一些构造方法和工厂方法可以用于从日期和时间转换,以及更多选项。更多信息请参阅 Java 文档中关于TemporalAccessor
的文档。
这些格式和对应的时间范围取决于你的需求,请根据实际情况选择合适的格式。
常见ISO格式有:
ISO_LOCAL_DATE:这种格式只有日期部分,不包含时间和时区,只保留至秒。
ISO_LOCAL_TIME:这种格式只有时间部分,不包含日期和时区,只保留至秒。
ISO_OFFSET_DATE_TIME:这种格式包含完整的日期和时间,以及时区。
INSTANT_SECONDS:这种格式包含完整日期、时间和时间戳(精确到秒)。
DATE_TIME_WITH_ZONE:这种格式只包含日期和时间,并且保留时区信息。
可以使用这些类来实现各种时间相关的功能,包括计算两个时刻之间的差值、比较日期的顺序、添加或减去时间段以及格式化日期和时间等。为了更方便地处理日期和时间,请考虑使用 Java 8 及更高版本,因为它们引入了许多新的改进 API 来解决这些问题。