标准时间和夏令时
Standard Time and Daylight Time
这不是真正的技术编程问题,但它与处理和显示 Java 中的时区有关。
在美国,有Eastern Time
和Pacific Time
这样的时区,在夏令时是Eastern Daylight Time
和Pacific Daylight Time
,而在夏令时没有生效,它们是 Eastern Standard Time
和 Pacific Standard Time
.
因此,由于夏令时从 3 月的第二个星期日开始,到 11 月的第一个星期日结束,因此可以说 3 月和 11 月之间的日期在 Eastern Standard Time
或 Pacific Standard Time
中无效?例如,以下日期在技术上不存在吗?
Tuesday, September 29, 2015 at 10 am PST
不应该是 Pacific Daylight Time (PDT)
,或者只是 PT
以避免必须指定 Daylight
或 Standard
?
在 Java 中使用 SimpleDateFormat
,指定任何一个似乎都是有效的。打印时,您可以看到夏令时转换在解析时发生,即使在调用 setLenient(false)
时也是如此。
示例:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMMM dd HH:mm:ss z");
sdf.setLenient(false);
Date d = sdf.parse("2015 September 29 10:00:00 PST");
System.out.println(d);
这输出:
Tue Sep 29 11:00:00 PDT 2015
它采用 PST(太平洋标准时间)并在输出时将其转换为 PDT(太平洋夏令时)。至少现在是这样。在撰写本文时,夏令时有效。
PDT 也被接受:
Date d2 = sdf.parse("2015 September 29 10:00:00 PDT");
System.out.println(d2);
这输出:
Tue Sep 29 10:00:00 PDT 2015
注意:这可能取决于是否具有美国语言环境。因为那是我的默认语言环境,所以上面的工作。如果这不是您的语言环境,请尝试在顶部的 SimpleDateFormat
构造函数调用中添加第二个参数 Locale.US
。
对 EDT
中的 date/time 说 EST
,例如7 月 4 日在纽约,是无效的,但我们人类通常不关心并随意使用 EST
。这是错误的,但我们还是这样做了。
在计算上,我们力求准确,所以肯定无效。
但 VGR 是对的。即使 7 月 4 日也可以在 "standard" 时间,如果您所在的地区不遵守夏令时。
... would saying that a date between March and November is in Eastern Standard Time or Pacific Standard Time be invalid?
如果您谈论的时区在特定时间不遵守该特定段,那么是的 - 它无效。东部标准时间始终为 UTC-5,东部夏令时始终为 UTC-4。如果你在说 UTC-4 时说 EST,那你就用错了。 (而且人们确实经常错误地使用它。)
但是,正如其他人所指出的那样,许多时区中的某些地点不遵守夏令时,即使它们周围的地区遵守夏令时也是如此。如果你在夏天说MST,它在凤凰城有效,但在洛杉矶无效。
... or just simply PT to avoid having to specify Daylight or Standard?
是的,您可以只说 PT
并省略 S
或 D
。它在电视上经常以这种方式完成,但在计算机上却不那么常见。此外,这不适用于世界各地的时区(伦敦使用 GMT 和 BST - 那里没有通用的通用缩写)。
正确的时区名称
"Pacific Daylight Time" 等名称不是真正的时区。他们的 3-4 字母代码既不标准化也不唯一。帮自己一个忙,忘记他们的一切。切勿在日期时间工作中使用 "PDT"、"EST" 等。
对于日期时间工作,学习使用 proper time zone names。它们采用大陆、斜杠和城市或地区的格式。这些不是任意的或方便的,每个都代表该时区的调整或定义的变化或异常的历史。
所以地理上的接近是无关紧要的。例如,西雅图比凤凰城离洛杉矶远得多。但是西雅图的官方时区是 America/Los_Angeles
,而亚利桑那州使用 America/Phoenix
。
虽然美国西海岸的大部分地区都使用 America/Los_Angeles
,但并非全部都使用。正如我们所说,亚利桑那州没有,阿拉斯加的 Metlakatla 也没有。但请注意,两者分别与 America/Los_Angeles
在 DST 和标准时移中使用的 -07:00 和 -08:00 偏移量重叠。 (见下文)
所以您必须做功课以了解官方时区涵盖任何特定位置。如果您在业务逻辑中还不知道,则必须询问用户。
使用框架,卢克
您不必担心夏令时何时开始和结束。为日期时间工作使用一个体面的框架。让框架处理有关 DST 的细节。如果您感兴趣的区域有变化的规则,您唯一担心的应该是让 tz
数据库在您的框架中保持最新。
java.time
对于 Java 8 及更高版本,选择的框架是新的内置 java.time framework. (Tutorial) Inspired by Joda-Time, defined by JSR 310, extended by the ThreeTen-Extra 项目。
ZoneId zoneId_Montréal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt_Now_Montréal = ZonedDateTime.now( zoneId_Montréal );
String outputNowMontréal = zdt_Now_Montréal.toString( );
outputNowMontréal : 2015-09-04T01:39:46.962-04:00[America/Montreal]
调整夏令时
Daylight Saving Time (DST) is the most common anomaly in date-time work. When jumping an hour ahead or an hour behind, that means some time-of-day values do not exist at all or occur twice in a day. As the ZonedDateTime.of
class 医生说:
Time-zone rules, such as daylight savings, mean that not every local date-time is valid for the specified zone, thus the local date-time may be adjusted.
该方法解释了 java.time 在进行必要调整时使用的规则。请务必研究它们以了解其行为。
文档还说,与其使用 ZonedDateTime.of
方法,我们通常应该使用 LocalDateTime
class to create a date-time from numbers. Then apply a ZoneId
to get a ZonedDateTime
by using a different ZonedDateTime.of
静态方法。
LocalDateTime localDateTime = LocalDateTime.of( 2015, 9, 29, 10, 0, 0 );
ZoneId zoneId_LosAngeles = ZoneId.of("America/Los_Angeles");
ZonedDateTime zdt_LosAngeles = ZonedDateTime.of( localDateTime, zoneId_LosAngeles ) ;
zdt_LosAngeles : 2015-09-29T10:00-07:00[America/Los_Angeles]
我们可以在其他两个时区中显示时间轴中的某个时刻。而 America/Los_Angeles
has standard & DST offsets of -08:00 & -07:00 respectively, America/Phoenix
(Arizona) has only -07:00, and America/Metlakatla
(阿拉斯加)只有 -08:00。
ZonedDateTime zdt_Phoenix = zdt_LosAngeles.withZoneSameInstant( ZoneId.of( "America/Phoenix" ) );
ZonedDateTime zdt_Metlakatla = zdt_LosAngeles.withZoneSameInstant( ZoneId.of("America/Metlakatla") );
zdt_Phoenix : 2015-09-29T10:00-07:00[America/Phoenix]
zdt_Metlakatla : 2015-09-29T09:00-08:00[America/Metlakatla]
在“Spring 提前”和“回退”日期调整 DST 的规则在 class 文档中进行了解释。
The local date-time is resolved to a single instant on the time-line. This is achieved by finding a valid offset from UTC/Greenwich for the local date-time as defined by the rules of the zone ID.
In most cases, there is only one valid offset for a local date-time. In the case of an overlap, when clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
In the case of a gap, when clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
乔达时间
如果Java8技术不可用,使用第三方Joda-Time框架(启发java.time)。顺便说一下,Joda-Time 在 Android 中工作,其他人提供的一些特殊构建有助于克服 Dalvik classloader 的一些问题。
避免旧 j.u.Date/Calendar
避免使用旧的 java.util.Date/.Calendar 和 java.text.SimpleDateFormat classes。这些 classes 是业界首次以复杂的方式处理日期时间的大胆尝试。但最终他们失败了,被证明是令人困惑、麻烦和有缺陷的。
ISO 8601
java.time 和 Joda-Time 都提供格式化程序,如果您必须将它们用于输出,它们将使用这些 3-4 字母代码生成日期时间值的字符串表示形式。但不要将它们用于数据存储、数据交换或解析。
出于这些目的,请了解 ISO 8601 标准字符串格式。 java.time 和 Joda-Time 在解析和生成字符串表示时默认使用 ISO 8601。
这不是真正的技术编程问题,但它与处理和显示 Java 中的时区有关。
在美国,有Eastern Time
和Pacific Time
这样的时区,在夏令时是Eastern Daylight Time
和Pacific Daylight Time
,而在夏令时没有生效,它们是 Eastern Standard Time
和 Pacific Standard Time
.
因此,由于夏令时从 3 月的第二个星期日开始,到 11 月的第一个星期日结束,因此可以说 3 月和 11 月之间的日期在 Eastern Standard Time
或 Pacific Standard Time
中无效?例如,以下日期在技术上不存在吗?
Tuesday, September 29, 2015 at 10 am PST
不应该是 Pacific Daylight Time (PDT)
,或者只是 PT
以避免必须指定 Daylight
或 Standard
?
在 Java 中使用 SimpleDateFormat
,指定任何一个似乎都是有效的。打印时,您可以看到夏令时转换在解析时发生,即使在调用 setLenient(false)
时也是如此。
示例:
SimpleDateFormat sdf = new SimpleDateFormat("yyyy MMMM dd HH:mm:ss z");
sdf.setLenient(false);
Date d = sdf.parse("2015 September 29 10:00:00 PST");
System.out.println(d);
这输出:
Tue Sep 29 11:00:00 PDT 2015
它采用 PST(太平洋标准时间)并在输出时将其转换为 PDT(太平洋夏令时)。至少现在是这样。在撰写本文时,夏令时有效。
PDT 也被接受:
Date d2 = sdf.parse("2015 September 29 10:00:00 PDT");
System.out.println(d2);
这输出:
Tue Sep 29 10:00:00 PDT 2015
注意:这可能取决于是否具有美国语言环境。因为那是我的默认语言环境,所以上面的工作。如果这不是您的语言环境,请尝试在顶部的 SimpleDateFormat
构造函数调用中添加第二个参数 Locale.US
。
对 EDT
中的 date/time 说 EST
,例如7 月 4 日在纽约,是无效的,但我们人类通常不关心并随意使用 EST
。这是错误的,但我们还是这样做了。
在计算上,我们力求准确,所以肯定无效。
但 VGR 是对的。即使 7 月 4 日也可以在 "standard" 时间,如果您所在的地区不遵守夏令时。
... would saying that a date between March and November is in Eastern Standard Time or Pacific Standard Time be invalid?
如果您谈论的时区在特定时间不遵守该特定段,那么是的 - 它无效。东部标准时间始终为 UTC-5,东部夏令时始终为 UTC-4。如果你在说 UTC-4 时说 EST,那你就用错了。 (而且人们确实经常错误地使用它。)
但是,正如其他人所指出的那样,许多时区中的某些地点不遵守夏令时,即使它们周围的地区遵守夏令时也是如此。如果你在夏天说MST,它在凤凰城有效,但在洛杉矶无效。
... or just simply PT to avoid having to specify Daylight or Standard?
是的,您可以只说 PT
并省略 S
或 D
。它在电视上经常以这种方式完成,但在计算机上却不那么常见。此外,这不适用于世界各地的时区(伦敦使用 GMT 和 BST - 那里没有通用的通用缩写)。
正确的时区名称
"Pacific Daylight Time" 等名称不是真正的时区。他们的 3-4 字母代码既不标准化也不唯一。帮自己一个忙,忘记他们的一切。切勿在日期时间工作中使用 "PDT"、"EST" 等。
对于日期时间工作,学习使用 proper time zone names。它们采用大陆、斜杠和城市或地区的格式。这些不是任意的或方便的,每个都代表该时区的调整或定义的变化或异常的历史。
所以地理上的接近是无关紧要的。例如,西雅图比凤凰城离洛杉矶远得多。但是西雅图的官方时区是 America/Los_Angeles
,而亚利桑那州使用 America/Phoenix
。
虽然美国西海岸的大部分地区都使用 America/Los_Angeles
,但并非全部都使用。正如我们所说,亚利桑那州没有,阿拉斯加的 Metlakatla 也没有。但请注意,两者分别与 America/Los_Angeles
在 DST 和标准时移中使用的 -07:00 和 -08:00 偏移量重叠。 (见下文)
所以您必须做功课以了解官方时区涵盖任何特定位置。如果您在业务逻辑中还不知道,则必须询问用户。
使用框架,卢克
您不必担心夏令时何时开始和结束。为日期时间工作使用一个体面的框架。让框架处理有关 DST 的细节。如果您感兴趣的区域有变化的规则,您唯一担心的应该是让 tz
数据库在您的框架中保持最新。
java.time
对于 Java 8 及更高版本,选择的框架是新的内置 java.time framework. (Tutorial) Inspired by Joda-Time, defined by JSR 310, extended by the ThreeTen-Extra 项目。
ZoneId zoneId_Montréal = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt_Now_Montréal = ZonedDateTime.now( zoneId_Montréal );
String outputNowMontréal = zdt_Now_Montréal.toString( );
outputNowMontréal : 2015-09-04T01:39:46.962-04:00[America/Montreal]
调整夏令时
Daylight Saving Time (DST) is the most common anomaly in date-time work. When jumping an hour ahead or an hour behind, that means some time-of-day values do not exist at all or occur twice in a day. As the ZonedDateTime.of
class 医生说:
Time-zone rules, such as daylight savings, mean that not every local date-time is valid for the specified zone, thus the local date-time may be adjusted.
该方法解释了 java.time 在进行必要调整时使用的规则。请务必研究它们以了解其行为。
文档还说,与其使用 ZonedDateTime.of
方法,我们通常应该使用 LocalDateTime
class to create a date-time from numbers. Then apply a ZoneId
to get a ZonedDateTime
by using a different ZonedDateTime.of
静态方法。
LocalDateTime localDateTime = LocalDateTime.of( 2015, 9, 29, 10, 0, 0 );
ZoneId zoneId_LosAngeles = ZoneId.of("America/Los_Angeles");
ZonedDateTime zdt_LosAngeles = ZonedDateTime.of( localDateTime, zoneId_LosAngeles ) ;
zdt_LosAngeles : 2015-09-29T10:00-07:00[America/Los_Angeles]
我们可以在其他两个时区中显示时间轴中的某个时刻。而 America/Los_Angeles
has standard & DST offsets of -08:00 & -07:00 respectively, America/Phoenix
(Arizona) has only -07:00, and America/Metlakatla
(阿拉斯加)只有 -08:00。
ZonedDateTime zdt_Phoenix = zdt_LosAngeles.withZoneSameInstant( ZoneId.of( "America/Phoenix" ) );
ZonedDateTime zdt_Metlakatla = zdt_LosAngeles.withZoneSameInstant( ZoneId.of("America/Metlakatla") );
zdt_Phoenix : 2015-09-29T10:00-07:00[America/Phoenix]
zdt_Metlakatla : 2015-09-29T09:00-08:00[America/Metlakatla]
在“Spring 提前”和“回退”日期调整 DST 的规则在 class 文档中进行了解释。
The local date-time is resolved to a single instant on the time-line. This is achieved by finding a valid offset from UTC/Greenwich for the local date-time as defined by the rules of the zone ID.
In most cases, there is only one valid offset for a local date-time. In the case of an overlap, when clocks are set back, there are two valid offsets. This method uses the earlier offset typically corresponding to "summer".
In the case of a gap, when clocks jump forward, there is no valid offset. Instead, the local date-time is adjusted to be later by the length of the gap. For a typical one hour daylight savings change, the local date-time will be moved one hour later into the offset typically corresponding to "summer".
乔达时间
如果Java8技术不可用,使用第三方Joda-Time框架(启发java.time)。顺便说一下,Joda-Time 在 Android 中工作,其他人提供的一些特殊构建有助于克服 Dalvik classloader 的一些问题。
避免旧 j.u.Date/Calendar
避免使用旧的 java.util.Date/.Calendar 和 java.text.SimpleDateFormat classes。这些 classes 是业界首次以复杂的方式处理日期时间的大胆尝试。但最终他们失败了,被证明是令人困惑、麻烦和有缺陷的。
ISO 8601
java.time 和 Joda-Time 都提供格式化程序,如果您必须将它们用于输出,它们将使用这些 3-4 字母代码生成日期时间值的字符串表示形式。但不要将它们用于数据存储、数据交换或解析。
出于这些目的,请了解 ISO 8601 标准字符串格式。 java.time 和 Joda-Time 在解析和生成字符串表示时默认使用 ISO 8601。