国际化项目开发中关于时间的问题三

一、ZonedDateTime 和 LocalDateTime 与 Date的区别

ZonedDateTime 和 LocalDateTime 与 Date 是 Java 中用于处理日期和时间的类,但它们之间存在显著差异。下面是它们的主要区别:

1. 引入时间
    Date: 属于 java.util 包,是 Java 早期版本中用于表示日期和时间的类,最早在 JDK 1.0 中引入。设计简单但存在诸多缺陷,如不直接支持时区、难以进行日期和时间操作等。
    ZonedDateTime 和 LocalDateTime: 属于 java.time 包,是 Java 8 中引入的新日期和时间 API 的一部分。新 API 提供了更强大、灵活的日期和时间处理功能,解决了 Date 类的许多问题。

2. 时区支持
    Date: 实际上是一个时间戳,表示从 1970 年 1 月 1 日 00:00:00 GMT(UTC)以来的毫秒数。Date 对象本身不包含时区信息,默认使用系统时区来解释其值。
    ZonedDateTime: 明确支持时区信息,包含了日期、时间和时区,可以准确地表示全球各地的时间。
    LocalDateTime: 不包含时区信息,仅表示本地的日期和时间,与时区无关。

3. 不可变性
    Date: 是可变的,即 Date 对象在创建后其值可以被修改。这容易导致线程安全问题。
    ZonedDateTime 和 LocalDateTime: 是不可变的,创建后不能修改。这种设计使得它们更加安全且适用于多线程环境。

4. 表示的内容
    Date: 实际上只是一个时间戳,并没有真正表示“日期”。通过 Date 对象可以提取日期和时间,但这些操作往往依赖于过时的 Calendar 类。
    ZonedDateTime: 表示带有时区的完整日期和时间,包括年、月、日、小时、分钟、秒、纳秒以及时区信息。
    LocalDateTime: 表示不带时区的日期和时间,包括年、月、日、小时、分钟、秒和纳秒。

5. 常用操作
    Date: 提供的操作有限,通常需要借助 Calendar 类进行日期运算,如加减天数、月份等。
    ZonedDateTime 和 LocalDateTime: 提供了丰富的操作方法,如日期加减、时间比较、日期计算、格式化等。

6. 格式化与解析
    Date: 格式化和解析通常通过 SimpleDateFormat 完成,这个类是线程不安全的,使用时需要特别注意。
    ZonedDateTime 和 LocalDateTime: 使用 DateTimeFormatter 进行格式化和解析。DateTimeFormatter 是线程安全的,并提供了更简洁和灵活的日期时间格式化支持。

7. 示例代码对比
    Date 示例:

    Date date = new Date();
    System.out.println("当前时间 (Date): " + date);

    ZonedDateTime 示例:

    ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of("Asia/Tokyo"));
    System.out.println("当前时间 (ZonedDateTime): " + zonedDateTime);

    LocalDateTime 示例:

    LocalDateTime localDateTime = LocalDateTime.now();
    System.out.println("当前时间 (LocalDateTime): " + localDateTime);

8. 兼容性
    Date: 是旧版 API,在许多现有的 Java 库中仍然被广泛使用。为了兼容性,有时需要将新 API(ZonedDateTime、LocalDateTime 等)与 Date 互相转换。
    ZonedDateTime 和 LocalDateTime: 是 Java 8 中引入的新 API,推荐在新项目中使用。它们提供了与 Date 的转换方法,如 Date.from(Instant) 和 ZonedDateTime.toInstant()。

9. 性能
    Date: 较为简单,性能开销较小,但由于其功能有限,使用起来不够灵活。
    ZonedDateTime 和 LocalDateTime: 功能强大,支持的操作更多,因此在某些复杂操作中可能略有性能开销,但通常这在现代应用中可以忽略不计。

10. 总结:
    Date 是一个旧版的时间类,功能有限且不便于使用,尤其是对时区的处理。
    ZonedDateTime 和 LocalDateTime 是 Java 8 引入的新时间 API,提供了更强大和灵活的日期和时间处理功能,推荐在新开发中使用。ZonedDateTime 特别适用于涉及全球不同时区的应用,
    而 LocalDateTime 适用于仅关心本地时间的应用。

二、ZonedDateTime和Instant代码案例

国际化开发推荐使用JDK 8新版本api ZonedDateTime,Instant,
废弃JDK 1.0 旧版本的Date类、Calender类
demo 展示场景
1:获取指定时区时间、指定时区时间转时间戳、时间戳转指定时区时间、时间操作(加减天数等)
2:通过常见的24个时区验证代码能否正常运行

import net.dreamlu.mica.core.utils.$;
import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.stream.Stream;

public class ZoneDateTimeTest {

    public static void main(String[] args) {

        Stream<Integer> integerStream = Stream.of(-11, -10, -9, -8, -7, -6, -5, -4, -3, -2, -1,
                0, +1, +2, +3, +4, +5, +6, +7, +8, +9, +10, +11);
        integerStream.forEach(zone -> {
            String zoneStr = zone.toString();
            System.out.println("时区=" + zone.toString());
            calcZoneAndTimestamp(zoneStr);
            System.out.println(" ");
        });
    }


    /*
     * 国际化开发推荐使用JDK 8新版本api ZonedDateTime,Instant,
     * 废弃JDK 1.0 旧版本的Date类、Calender类
     * demo 展示场景
     * 1:获取指定时区时间、指定时区时间转时间戳、时间戳转指定时区时间、时间操作(加减天数等)
     * 2:通过常见的24个时区验证代码能否正常运行
     *
     **/
    static public void calcZoneAndTimestamp(String zone) {
        if ($.isNotEqual("UTC", zone) && !zone.startsWith("-") && !zone.startsWith("+")) {
            zone = "+".concat(zone);
        }
        // 指定时区,例如 +9
        ZoneId zoneId = ZoneId.of(zone);

        // 获取指定时区的当前时间
        ZonedDateTime zonedDateTime1 = ZonedDateTime.now(zoneId);
        System.out.println("当前时间 (指定时区): " + zonedDateTime1);

        // 获取当前时间到第二天凌晨的时间
        ZonedDateTime zonedDateTime2 = zonedDateTime1.truncatedTo(ChronoUnit.DAYS).plusDays(1);
        System.out.println("第二天凌晨时间 (指定时区): " + zonedDateTime2);
        System.out.println("--------------------------------------------");

        // 将ZonedDateTime转换为时间戳(秒数)
        long timestamp1 = zonedDateTime1.toInstant().toEpochMilli();
        long timestamp2 = zonedDateTime2.toInstant().toEpochMilli();

        // 输出时间戳
        System.out.println("当前时间的时间戳 (毫秒): " + timestamp1);
        System.out.println("第二天凌晨时间的时间戳 (毫秒): " + timestamp2);
        System.out.println("--------------------------------------------");

        // 将时间戳转换为Instant
        Instant instant1 = Instant.ofEpochMilli(timestamp1);
        // 将Instant转换为指定时区的ZonedDateTime
        ZonedDateTime zonedDateTime11 = instant1.atZone(zoneId);

        // 将时间戳转换为Instant
        Instant instant2 = Instant.ofEpochMilli(timestamp2);
        // 将Instant转换为指定时区的ZonedDateTime
        ZonedDateTime zonedDateTime22 = instant2.atZone(zoneId);
        // 输出指定时区的时间

        // 指定格式化输出
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format11 = zonedDateTime11.format(formatter);
        System.out.println("(指定输出格式) 当前时间的时间戳 (毫秒) 转换为时间 (指定时区): " + format11);

        String format22 = zonedDateTime22.format(formatter);
        System.out.println("(指定输出格式)  第二天凌晨时间的时间戳 (毫秒)  转换为时间 (指定时区): " + format22);
        System.out.println("--------------------------------------------");

    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值