LocalDateTime和ZonedDateTime

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.
     * <p>
     * This will query the {@link Clock#systemDefaultZone() system clock} in the default
     * time-zone to obtain the current date.
     * <p>
     * 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)
}

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值