LocalDateTime是Java8引入的新的时间的表示方式。是的,你没看错,他发由他发,我用Java8。
LocalDateTime,直译就是当地的日期时间,既然是当地的日期时间,不包含时区概念。
A date-time without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30.
This class does not store or represent a time-zone. Instead, it is a description of the date, as used for birthdays, combined with the local time as seen on a wall clock. It cannot represent an instant on the time-line without additional information such as an offset or time-zone.
在ISO-8601的标准日历系统中,日期时间是没有时区的,就像2007-12-03T10:15:30.
这个类不存储或者表示时区。相反,它是对日期的描述,用于生日,结合挂钟上的当地时间。 如果没有诸如偏移或时区之类的附加信息,它就不能代表时间线上的瞬间。
LocalDateTime由两部分组成:LocalDate与LocalTime
获取当前的日期
fun main() {
var now = LocalDate.now()
println(now.toString())
}
输出的结果是:
2022-02-02
这里表示的是当前的日期,2022年2月2日,但是这个并不是说没有时区,而是表示的当前默认时区。
//-----------------------------------------------------------------------
/**
* Obtains the current date from the system clock in the default time-zone.
*
* This will query the {@link Clock#systemDefaultZone() system clock} in the default
* time-zone to obtain the current date.
*
* Using this method will prevent the ability to use an alternate clock for testing
* because the clock is hard-coded.
*
* @return the current date using the system clock and default time-zone, not null
*/
public static LocalDate now() {
return now(Clock.systemDefaultZone());
}
当然了,这个now方法是可以传入一个时区的
public static LocalDate now(ZoneId zone) {
return now(Clock.system(zone));
}
public static LocalDate now(Clock clock) {
Objects.requireNonNull(clock, "clock");
final Instant now = clock.instant(); // called once
return ofInstant(now, clock.getZone());
}
由于不表示时区,那么即使设置了时区,输出的字符串还是一样的:
fun main() {
var now = LocalDate.now()
println(now.toString())
println(LocalDate.now(ZoneId.of("UTC")))
}
输出的结果是:
2022-02-02
2022-02-02
获取当前的时间:
fun main() {
var now = LocalTime.now()
println(now)
}
输出的结果是:
11:15:11.081522
与LocalDate一样,都不表示时区。
public static LocalTime now() {
return now(Clock.systemDefaultZone());
}
public static LocalTime now(ZoneId zone) {
return now(Clock.system(zone));
}
public static LocalTime now(Clock clock) {
Objects.requireNonNull(clock, "clock");
final Instant now = clock.instant(); // called once
return ofInstant(now, clock.getZone());
}
fun main() {
var now = LocalDateTime.now()
println(now)
}
输出的结果是:
2022-02-02T11:22:22.287480
反正都是不表示时区,我不高兴再贴源码了。
可以看到,LocalDateTime有很多方法,可以通过LocalDate和LocalTime构造时间。
fun main() {
val localDate = LocalDate.now()
val localTime = LocalTime.now()
val localDateTime = LocalDateTime.of(localDate, localTime)
println(localDateTime)
}
输出的结果为
2022-02-03T20:30:42.802526
从字符串中解析出日前时间,那么就需要一个pattern。在Java8之前,最常用的一个解析是SimpleDateFormat,简单示例如下:
fun main() {
var simpleDateFormat = SimpleDateFormat("yyyy.MM.dd")
simpleDateFormat.timeZone = TimeZone.getTimeZone("Asia/Shanghai")
println(simpleDateFormat.parse("2022.02.03"))
}
输出的结果
Thu Feb 03 00:00:00 CST 2022
可以看到这个CST时间,我不太懂这个时间,所以我也不推荐使用这个方法。
最为重要的是,这个SimpleDateFormat类是一个非线程安全的类,在Java8及以后的代码中,推荐使用线程安全的类DateTimeFormatter.
fun main() {
var dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss")
println(LocalDateTime.parse("2022.02.03 21:45:34", dateTimeFormatter))
}
解析出来的时间是:
2022-02-03T21:45:34
这个时间的是没有时区的概念的。那么如果需要时区应该怎么办?那就来到了ZonedDateTime.
时区是一个很伟大发明,但是用不好就会造成混乱,尤其是程序部署在不同时区的服务器上时,比较时间会略显麻烦。在Java8中引入的ZonedDateTime,是一个标准的带时区的日期时间。
A date-time with a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.
This class handles conversion from the local time-line of LocalDateTime to the instant time-line of Instant. The difference between the two time-lines is the offset from UTC/Greenwich, represented by a ZoneOffset在 ISO-8601 日历系统中具有时区的日期时间,例如 2007-12-03T10:15:30+01:00 Europe/Paris。
此类处理从 LocalDateTime 的本地时间线到 Instant 的即时时间线的转换。 两条时间线之间的差异是与 UTC/格林威治的偏移量,由 ZoneOffset 表示
fun main() {
println(ZonedDateTime.now())
}
输出结果
2022-02-03T20:55:33.127310+08:00[Asia/Shanghai]
可以看到,这里明显的特征是加入了时区,查看源码:
public static ZonedDateTime now() {
return now(Clock.systemDefaultZone());
}
public static ZonedDateTime now(Clock clock) {
Objects.requireNonNull(clock, "clock");
final Instant now = clock.instant(); // called once
return ofInstant(now, clock.getZone());
}
这是获取的当前系统时区,那么我也可以手动设置时区:
public static ZonedDateTime now(ZoneId zone) {
return now(Clock.system(zone));
}
即
fun main() {
println(ZonedDateTime.now())
println(ZonedDateTime.now(ZoneId.of("UTC")))
}
输出的结果为
2022-02-03T21:08:31.065378+08:00[Asia/Shanghai]
2022-02-03T13:08:31.065918Z[UTC]
可以清楚的看到,时区的差异,时间相差8个小时。
把2022年2月3日转换成ZonedDateTime。
fun main() {
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日")
val localDate = LocalDate.parse("2022年02月03日", dateTimeFormatter)
val localTime = LocalTime.of(0, 0, 0)
println(ZonedDateTime.of(localDate, localTime, ZoneId.of("Asia/Shanghai")))
}
输出的结果为
2022-02-03T00:00+08:00[Asia/Shanghai]
但是这样有点不太简洁,查阅源码,可以试试下面这么写:
fun main() {
val dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy年MM月dd日")
val zonedDateTime = LocalDate.parse("2022年02月03日", dateTimeFormatter).atStartOfDay(ZoneId.of("Asia/Shanghai"))
println(zonedDateTime)
}
别问,问就是要时刻重构。