LocalDateTime和ZonedDateTime

文章目录

  • 1.LocalDateTime
    • 1.1 LocalDate
    • 1.2 LocalTime
    • 1.3 LocalDateTime的获取
    • 1.4 时间的转换
  • 2. 时间解析
    • 2.1 LocalDateFormatter
  • 3. ZonedDateTime
    • 3.1 简单使用
  • 4.实际使用
    • 4.1 需求
    • 4.2 解析
    • 4.3 答案

1.LocalDateTime

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

1.1 LocalDate

获取当前的日期

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

1.2 LocalTime

获取当前的时间:

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());
}        

1.3 LocalDateTime的获取

fun main() {
    var now = LocalDateTime.now()
    println(now)
}

输出的结果是:

2022-02-02T11:22:22.287480

反正都是不表示时区,我不高兴再贴源码了。

1.4 时间的转换

可以看到,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

2. 时间解析

从字符串中解析出日前时间,那么就需要一个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.

2.1 LocalDateFormatter

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.

3. 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 表示

3.1 简单使用

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个小时。

4.实际使用

4.1 需求

把2022年2月3日转换成ZonedDateTime。

4.2 解析

  • 要指明时区,这里没有说,那就明确指明为东八区时间,以防止不同服务器的设置代理不同,切不要使用系统默认。
  • 没有指明时分秒,那就可以从零点零分零秒开始。
  • 代码要尽量简单明确。

4.3 答案

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)
}

别问,问就是要时刻重构。

你可能感兴趣的:(java,java)