了解特定的 UTC 时间格式 YYYY-MM-DDTHH:MM:SS。断续器

2022-09-03 14:35:42

我有两个相关的问题。

假设在 BST 中运行的程序在 UTC YYYY-MM-DDTHH:MM:SS 中生成当前时间的日期时间值。SSSZ 格式

同时假设伦敦当前时间为 2016-06-01 12:33:54

  1. 如果程序给出的当前时间是 2016-06-01T11:33:54.000Z ,程序有误吗?

  2. BST 的夏季偏移量如何记录在 YYYY-MM-DDTHH:MM:SS 的相应时间格式中。断续器

我假设 YYYY-MM-DDTHH:MM:SS+0001 我是对的吗?


答案 1

首先,请阅读iso8601信息。处理不同时区(例如服务器时区和客户端时区)的时间变得越来越普遍,并且该标准非常有用。

特别是请在此处阅读有关UTC或“祖鲁”时间的信息

  1. 该程序是正确的,因为伦敦时间比夏季的“UTC”时间早一个小时

  2. 尾随的“Z”是UTC(祖鲁语)的缩写。您也可以写“+00:00”而不是“Z”。党卫军。SSS 是指秒和毫秒 - 与时区无关。在devnull的评论中,他向您展示了如何为夏季应用偏移量。

编辑

评论中有一些关于iso8601时区是否包括时区的讨论,以及时区是否真的会被打印出来。

这完全取决于日期/时间实现。如果我们使用,则支持时区并将打印。SimpleDateFormat

下面是一个用于说明的代码示例

SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
formatter.setTimeZone(TimeZone.getTimeZone("UTC"));
System.out.println(formatter.format(new Date()));
formatter.setTimeZone(TimeZone.getTimeZone("Europe/London"));
System.out.println(formatter.format(new Date()));

输出

2016-06-02T12:53:14.924Z
2016-06-02T13:53:14.925+01:00

当然,如果您使用的是不同的日期/时间库,例如 ,则估计详细信息将有所不同。joda-time

编辑:正如@DerrylThomas明智地指出的那样,多年来使用小写y - 除非它打算使用周年 - 在类似问题的另一个答案中详细解释 https://stackoverflow.com/a/56911450SimpleDateFormat


答案 2

如果程序给出的当前时间是 2016-06-01T11:33:54.000Z ,程序有误吗?

格式正确,符合 ISO 8601 标准,但不代表欧洲/伦敦时间。在 2016 年的伦敦,DST 从 3 月 27 日星期日凌晨 1:00 开始,到 10 月 30 日星期日凌晨 2:00 结束,因此,欧洲/伦敦在这段时间内的日期时间表示形式应具有小时数的时区偏移量。at 末尾指定时间,即 UTC 时间,因此具有小时时区偏移量。对于欧洲/伦敦,同一时刻可以表示为 。+01:00ZZulu+00:002016-06-01T12:33:54+01:00

java.time

日期时间 API 及其格式化 API 已过时且容易出错。建议完全停止使用它们,并切换到 现代日期时间 API* java.utilSimpleDateFormatjava.time

甚至Joda-Time也不应该再使用。请注意Joda-Time主页上的以下说明

Joda-Time是Java SE 8之前Java事实上的标准日期和时间库。现在要求用户迁移到 java.time (JSR-310)。

java.timeAPI基于日期时间字符串,可以解析为不需要日期时间解析/格式化类型。ISO 86012016-06-01T11:33:54.000Zjava.time.ZonedDateTimejava.time.OffsetDateTime

演示:

import java.time.ZoneId;
import java.time.ZonedDateTime;

public class Main {
    public static void main(String[] args) {
        ZonedDateTime zdt = ZonedDateTime.parse("2016-06-01T11:33:54.000Z");
        System.out.println(zdt);

        ZoneId zoneId = ZoneId.of("Europe/London");
        ZonedDateTime zdtInLondon = zdt.withZoneSameInstant(zoneId);
        System.out.println(zdtInLondon);
    }
}

输出:

2016-06-01T11:33:54Z
2016-06-01T12:33:54+01:00[Europe/London]

如何处理夏令时 (DST)?

如前所述,日期时间字符串也可以解析为不需要日期时间解析/格式化类型。但是,它被设计为处理固定的时区偏移量,而被设计为处理时区,因此它会自动处理DST。如果需要,您可以使用 ZonedDateTime# 将 a 转换为OffsetDateTime2016-06-01T11:33:54.000Zjava.time.OffsetDateTimeOffsetDateTimeZonedDateTimeZonedDateTimeOffsetDateTime

import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd'T'HH:mm:ss.SSS z", Locale.ENGLISH);

        String strDateTime = "2016-03-01T11:33:54.000 Europe/London";
        ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);

        strDateTime = "2016-06-01T11:33:54.000 Europe/London";
        zdt = ZonedDateTime.parse(strDateTime, dtf);
        System.out.println(zdt);
    }
}

输出:

2016-03-01T11:33:54Z[Europe/London]
2016-06-01T11:33:54+01:00[Europe/London]

请注意时区偏移量如何自动从 更改为 反映 DST 更改。另一方面Z01:00

import java.time.OffsetDateTime;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2016-03-01T11:33:54.000+01:00";
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
        System.out.println(odt);

        strDateTime = "2016-06-01T11:33:54.000+01:00";
        odt = OffsetDateTime.parse(strDateTime);
        System.out.println(odt);
    }
}

输出:

2016-03-01T11:33:54+01:00
2016-06-01T11:33:54+01:00

在这种情况下,您不会谈论时区(例如欧洲/伦敦);相反,您谈论的是小时的固定时区偏移量。+01:00

从跟踪:日期时间中了解有关现代日期时间 API 的更多信息


*出于任何原因,如果你必须坚持使用Java 6或Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能反向移植到Java 6和7。如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请查看通过desugaring提供的Java 8 +API如何在Android项目中使用ThreeTenABP


推荐