Java中,使用 ZonedDateTime 可以避免时区相关的时间问题,但在某些业务场景下,LocalDateTime 足够使用且更简单。 在处理跨时区应用程序时,确保使用 ZonedDateTime 或 OffsetDateTime 以避免时区转换错误。本文主要介绍将带有时区别的时间,ZonedDateTime转换成LocalDateTime本地时间(不带有时区的时间)的方法及代码。

1、ZonedDateTime与LocalDateTime区别

LocalDateTime:这基本上是一个美化的字符串表示日期和时间;它与时区无关,这意味着它不代表时间轴上的任何时间点

Instant:这是自EPOCH以来经过的时间的毫秒表示。这表示时间轴上的特定时刻

ZonedDateTime:这也表示时间轴上的某个时刻,但它表示为带有时区的日期和时间

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // 创建一个 LocalDateTime 对象,表示 2018 年 10 月 25 日 12:00 PM
        LocalDateTime localDateTime = LocalDateTime.of(2018, 10, 25, 12, 0, 0);
        // 将 LocalDateTime 转换为 UTC 时区的 ZonedDateTime
        ZonedDateTime zonedDateTimeInUTC = localDateTime.atZone(ZoneId.of("UTC"));
        // 将 UTC 时区的 ZonedDateTime 转换为 America/New_York 时区的 ZonedDateTime
        ZonedDateTime zonedDateTimeInEST = zonedDateTimeInUTC.withZoneSameInstant(ZoneId.of("America/New_York"));

        // 输出 LocalDateTime 对象(不包含时区)
        System.out.println(localDateTime.toString()); // 输出: 2018-10-25T12:00
        // 输出 UTC 时区的 ZonedDateTime 对象
        System.out.println(zonedDateTimeInUTC.toString()); // 输出: 2018-10-25T12:00Z[UTC]
        // 输出 America/New_York 时区的 ZonedDateTime 对象
        System.out.println(zonedDateTimeInEST.toString()); // 输出: 2018-10-25T08:00-04:00[America/New_York]

        // 示例 2: 创建一个表示当前日期的 ZonedDateTime 对象,时间为 11:30 AM,时区为 UTC
        ZonedDateTime z = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);
        // 输出与 UTC 同一瞬间的 US/Central 时区的时间
        System.out.println(z.withZoneSameInstant(ZoneId.of("US/Central")));
    }
}

2、转换ZonedDateTime成本地时区时间LocalDateTime

import java.time.LocalDateTime;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        // 将 UTC 时间转换为 Zurich(瑞士)时区的本地时间
        // 创建一个 ZonedDateTime 对象,时间为 UTC 时区的 11:30
        ZonedDateTime utcZoned = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

        // 定义瑞士 Zurich 时区的 ZoneId
        ZoneId swissZone = ZoneId.of("Europe/Zurich");

        // 将 UTC 时间转换为 Zurich 时区的同一时刻
        ZonedDateTime swissZoned = utcZoned.withZoneSameInstant(swissZone);

        // 将转换后的 Zurich 时区的 ZonedDateTime 对象转换为 LocalDateTime 对象
        LocalDateTime swissLocal = swissZoned.toLocalDateTime();

        // 输出 Zurich 时区的本地时间
        System.out.println("Zurich LocalDateTime: " + swissLocal);

        // 将 UTC 时间转换为 US/Central 时区的同一时刻
        // 再次创建一个 UTC 时区的 11:30 的 ZonedDateTime 对象
        ZonedDateTime z = ZonedDateTime.of(LocalDate.now().atTime(11, 30), ZoneOffset.UTC);

        // 将 UTC 时间转换为 US/Central 时区的同一时刻,并输出结果
        System.out.println("US/Central ZonedDateTime: " + z.withZoneSameInstant(ZoneId.of("US/Central")));
    }
}

3、时区可用值

注意:没有全部列出,只是其中一部分。

Asia/Shanghai
Universal
Europe/Zagreb
America/Port_of_Spain
Europe/Helsinki
Asia/Beirut
Asia/Tel_Aviv
Pacific/Bougainville
US/Central
Africa/Sao_Tome
Indian/Chagos
America/Cayenne
Asia/Yakutsk
Pacific/Galapagos
Australia/North
Europe/Paris
Africa/Ndjamena
Pacific/Fiji
America/Rainy_River
Indian/Maldives
Australia/Yancowinna
SystemV/AST4
Asia/Oral
America/Yellowknife
Pacific/Enderbury
America/Juneau
Australia/Victoria
America/Indiana/Vevay
Asia/Tashkent
Asia/Jakarta
Africa/Ceuta
Asia/Barnaul
America/Recife
America/Buenos_Aires
America/Noronha
America/Swift_Current
Australia/Adelaide
America/Metlakatla
Africa/Djibouti
America/Paramaribo
Europe/Simferopol
Europe/Sofia
Africa/Nouakchott
Europe/Prague
America/Indiana/Vincennes
Antarctica/Mawson
America/Kralendijk
Antarctica/Troll
Europe/Samara
Indian/Christmas
America/Antigua
Pacific/Gambier
America/Indianapolis
America/Inuvik
America/Iqaluit
Pacific/Funafuti
UTC
Antarctica/Macquarie
Canada/Pacific
America/Moncton
Africa/Gaborone
Pacific/Chuuk
Asia/Pyongyang
America/St_Vincent
Asia/Gaza
Etc/Universal
PST8PDT
Atlantic/Faeroe
Asia/Qyzylorda
Canada/Newfoundland
America/Kentucky/Louisville
America/Yakutat
Asia/Ho_Chi_Minh
Antarctica/Casey
Europe/Copenhagen
Africa/Asmara
Atlantic/Azores
Europe/Vienna
ROK
Pacific/Pitcairn
America/Mazatlan
Australia/Queensland
Pacific/Nauru
Europe/Tirane
Asia/Kolkata
SystemV/MST7
Australia/Canberra
MET
Australia/Broken_Hill
Europe/Riga
America/Dominica
Africa/Abidjan
America/Mendoza
America/Santarem
Kwajalein
America/Asuncion
Asia/Ulan_Bator
NZ
America/Boise
Australia/Currie
EST5EDT
Pacific/Guam
Pacific/Wake
Atlantic/Bermuda
America/Costa_Rica
America/Dawson
Asia/Chongqing
Eire
Europe/Amsterdam
America/Indiana/Knox
America/North_Dakota/Beulah
Africa/Accra
Atlantic/Faroe
Mexico/BajaNorte
America/Maceio
Etc/UCT
Pacific/Apia

推荐文档