一些时区 return IllegalArgumentException
Some Time Zones return IllegalArgumentException
此代码示例使用 3 个时区(EST、PST、EET)。
对于每个时区,都会创建一个 Date 对象,并且 toString() 是 运行 打印出正在使用的格式。
然后将这个相同的字符串值传递给构造函数并用于创建新的日期对象。
该代码执行 运行 检查以确保所使用的时区有效。
所有 3 个时区(EST、PST、EET)均有效,但在创建对象时,仅针对 EET 返回 java.lang.IllegalArgumentException。
import java.util.*;
import java.text.*;
public class DateTest
{
public static void main (String[] args)
{
System.out.println("=======Test 1 : using EST=======");
isValidTimeZone("EST");
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
runTest();
System.out.println("=======Test 2 : using PST=======");
isValidTimeZone("PST");
TimeZone.setDefault(TimeZone.getTimeZone("PST"));
runTest();
System.out.println("=======Test 3 : using EET=======");
isValidTimeZone("EET");
TimeZone.setDefault(TimeZone.getTimeZone("EET"));
runTest();
}
private static void isValidTimeZone(String tz)
{
String[] validIDs = TimeZone.getAvailableIDs();
boolean validTZ = false;
for (String str : validIDs) {
if (str != null && str.equals(tz)) {
validTZ = true;
break;
}
}
if (validTZ)
{
System.out.println(tz + " is a Valid Time Zone");
}
else
{
System.out.println(tz + " is **NOT** a Valid Time Zone");
}
}
private static void runTest()
{
try
{
String myDateString = new Date().toString();
System.out.println(" Default Date String : " + myDateString);
MyObjectWithADate myObject = new MyObjectWithADate(new Date(myDateString));
}
catch(Exception e)
{
System.out.println(" Object NOT Created!!!!!");
e.printStackTrace(System.out);
}
}
}
public MyObjectWithADate (Date eventDate)
{
System.out.println(" Passed in Date : " + eventDate.toString());
// this.eventDate = eventDate;
try {
this.eventDate = DateFormat.getInstance().parse(eventDate.toString());
System.out.println(" Object Created");
} catch (ParseException e) {
System.out.println(" Object NOT Created");
e.printStackTrace();
}
}
}
这是输出。
基于 Java 11 文档,它确实评论说 Date 已被弃用,应该使用 DateFormat.parse()。
作为测试,对象的代码被修改为使用 DateFormat.parse,但这只会让事情变得更糟。
public MyObjectWithADate (Date eventDate)
{
System.out.println(" Passed in Date : " + eventDate.toString());
// this.eventDate = eventDate;
try {
this.eventDate = DateFormat.getInstance().parse(eventDate.toString());
System.out.println(" Object Created");
} catch (ParseException e) {
System.out.println(" Object NOT Created");
e.printStackTrace();
}
}
}
这是新的结果。
问题 1 :
JVM从哪个环境变量获取时区?
问题 2 :
使用原始代码,为什么使用与JVM提供的格式相同的格式时会出现异常?
问题 3 :
EET 具体是什么导致它在 EST 和 PST 上失败并且可以毫无问题地交换?
问题 4 :
如果我想让任何时区的任何人都可以使用原始代码 运行,需要更改什么?
编辑添加以下内容:
以上代码是按比例缩小的模型。不幸的是,无法在所有地方修改实际代码以更改使用 Date 对象。
我使用 MyObjectWithADate 对象中的 SimpleDateFormat 做了 运行 另一个测试。这再次适用于 EST 和 PST,但不适用于 EET。
class MyObjectWithADate
{
private Date eventDate;
public MyObjectWithADate (Date eventDate)
{
System.out.println(" Passed in Date : " + eventDate.toString());
String datePattern = new String ("E MMM dd HH:mm:ss z yyyy");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
try {
this.eventDate = simpleDateFormat.parse(eventDate.toString());
System.out.println(" Object Created");
} catch (ParseException e) {
System.out.println(" Object NOT Created");
e.printStackTrace();
}
System.out.println(" Object Created");
}
}
我开始觉得我原来的问题应该是,如何取下面的字符串
3 月 26 日星期五 21:42:522021 年东部时间
并将其放入日期对象中。
问题一:
这里是相关的doc
Gets the default TimeZone of the Java virtual machine. If the cached
default TimeZone is available, its clone is returned. Otherwise, the
method takes the following steps to determine the default time zone.
- Use the user.timezone property value as the default time zone ID if
it's available.
- Detect the platform time zone ID. The source of the
platform time zone and ID mapping may vary with implementation.
- Use
GMT as the last resort if the given or detected time zone ID is
unknown.
问题 2、3 和 4:
当您使用已弃用的 new Date(myString)
函数时,会抛出 EET 异常。我不确定这种方法的内部工作原理。但是为什么要打扰呢?它被弃用是有原因的。
如果您想从输入字符串创建日期对象。 Whosebug 上已经有大量关于此的答案。无论如何你真的不需要使用 new Date(string)
。这里有两个快速解决方案来获得你想要的东西。我假设您希望将日期字符串格式化为 java.util.Date
将打印出来的格式。如果这不准确,请使用 this link 创建您自己的格式。
1.使用 java.util.Date
(旧的,最好避免使用):
SimpleDateFormat oldJavaDateFormat = new SimpleDateFormat("EEE LLL dd HH:mm:ss z yyyy");
TimeZone.setDefault(TimeZone.getTimeZone("EET"));
//Surround with try/catch or throw
Date eventDate = oldJavaDateFormat.parse(new Date().toString());
//or if you need a date from some given date string
oldJavaDateFormat.parse("Thu Jan 13 15:13:13 EET 2033");
结果:
Fri Mar 26 20:52:40 EET 2021
2。使用新的java.time
(首选):
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE LLL dd HH:mm:ss z yyyy");
ZonedDateTime eventDate = ZonedDateTime.parse(new Date().toString(), formatter).withZoneSameLocal(ZoneId.of("EET"));
//or directly from a string
eventDate = ZonedDateTime.parse("Thu Jan 13 15:13:13 EET 2033", formatter);
结果:
2021-03-26T20:52:40+02:00[EET]
或者对于第二种情况(给定的字符串):
2033-01-13T15:13:13+02:00[Europe/Bucharest]
编辑:
使用上面的第一个解决方案,需要注意时区。在 SimpleDateFormat
对象上调用 parse()
可能无法按预期工作。您可能会丢失时区信息。
EST、PST 和 EET 不是时区
- EST是东部标准时间的缩写,又可以指澳大利亚东部标准时间和北美东部标准时间。
- 北美大部分地区在标准时间使用 EST,在夏令时 (DST) 使用东部夏令时 (EDT),这是一年中的大部分时间。所以这个意义上的EST可以看作是半个时区。
- 同样在澳大利亚的一些时区,一年中的大部分时间都使用 EST、EDT 或 AEDT。
- PST 可能是皮特凯恩标准时间、太平洋标准时间和菲律宾标准时间的缩写。 北美使用太平洋标准时间的所有 个地方目前都在太平洋夏令时。
- EET 可能没有歧义,可能只是指东欧时间,这是几个时区的通用名称,其中大部分时间在一年中的大部分时间都在东欧夏令时。
有效时区 Java
在 Java 中,您应该使用 Australia/Sydney、Pacific/Pitcairn 和 Europe/Bucharest 等时区 ID。总是 region/city 格式。它们表示明确的实时时区。在某些情况下,您可能能够说服 Java 将三个字母的缩写解释为时区,但由于它们经常是模棱两可的,而且通常不是真正的时区,因此不鼓励这样做。此外,当被识别为时区 ID 时,它们将被弃用。
要确定 Java 是否将给定的时区 ID 识别为有效,请使用来自 java.time 的 ZoneId
class、现代 Java 日期和时间 API,及其 of
方法。例如:
try {
ZoneId.of("EST");
System.out.println("EST is a valid time zone");
} catch (ZoneRulesException zre) {
System.out.println("EST is *not* a valid time zone");
}
输出:
EST is *not* a valid time zone
这会告诉您 Australia/Sydney、Pacific/Pitcairn、Europe/Bucharest 和 EET 都是有效时区。它还会告诉您 PST 不是。
为了与使用不推荐使用的时区缩写的旧代码一起使用,ZoneId
通过其 SHORT_IDS
常量对其中某些缩写提供额外支持。
System.out.println("" + ZoneId.SHORT_IDS.containsKey("EST")
+ " -> " + ZoneId.SHORT_IDS.get("EST"));
System.out.println("" + ZoneId.SHORT_IDS.containsKey("PST")
+ " -> " + ZoneId.SHORT_IDS.get("PST"));
System.out.println("" + ZoneId.SHORT_IDS.containsKey("EET")
+ " -> " + ZoneId.SHORT_IDS.get("EET"));
true -> -05:00
true -> America/Los_Angeles
false -> null
我们注意到,EST 全年都被理解为北美东部标准时间,而 PST
在标准时间期间被理解为北美太平洋标准时间,在夏季被理解为太平洋夏令时。 EET 在没有 SHORT_IDS
的情况下得到支持,因此此处不再赘述。
为什么您观察到令人惊讶的结果
Date.toString()
打印的缩写与 ZoneId
和 TimeZone
识别的缩写不同。您注意到当 PST
被设置为默认时区时,PDT
被打印为 Date
。编辑:另一个例子:PRC 是一个已弃用的时区 ID。 TimeZone
认得。 Date
将其打印为 CST
。 PRC 代表中华人民共和国。 CST Date
表示中国标准时间,而 TimeZone
将 CST
理解为北美中部标准时间。
被弃用的 Date(String)
构造函数识别的唯一时区是 GMT、UT、UTC、EST、CST、MST、PST、EDT、CDT、MDT 和 PDT。这解释了为什么 EET
不起作用。 我相信这可以回答您的问题 2. 和 3.
SimpleDateFormat
识别的时区缩写是另一回事。它们是特定于区域设置的,因为对于给定的时区,每个区域设置可能都有自己的 abbreviation/s。没有记录如何解释不明确的时区缩写,但已知它不稳定。在不同的 Java 安装中观察到相同缩写的不同结果。
最后,DateFormat.getInstance()
期望(或生成)的语法也是特定于语言环境的,所以我不希望它能识别您的任何字符串。它也没有在您的代码中。例如,在我的语言环境中 DateFormat.getInstance()
需要一个类似于 "27/03/2021 15.04"
的字符串。
无论如何,我建议您忘记 classes TimeZone
、Date
、SimpleDateFormat
和 DateFormat
。它们的设计都很糟糕,而且早已过时。我建议您将此作为问题 4 的部分答案。
动态设置 JVM 的默认时区也是非常危险的。此更改会影响您的程序的所有部分以及同一 JVM 中 运行 的其他程序,因此您可能会遇到难以追踪到您的代码的意外风险。我建议你不要。
问题 4 : 如果我想允许任何时区的任何人 运行 原始代码,需要更改什么?
首先,我建议您对所有日期和时间工作使用 java.time。
如果您可以控制使用哪些时区 ID:
public static void test(String timeZoneId) {
try {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(timeZoneId));
System.out.println(now);
} catch (ZoneRulesException zre) {
System.out.println("Not a valid time zone ID: " + timeZoneId);
}
}
试试看:
test("Australia/Sydney");
test("Pacific/Pitcairn");
test("Europe/Bucharest");
2021-03-27T07:49:27.095653+11:00[Australia/Sydney]
2021-03-26T12:49:27.100300-08:00[Pacific/Pitcairn]
2021-03-26T22:49:27.101219+02:00[Europe/Bucharest]
如果您需要适应已弃用的时区缩写,我非常不确定该建议什么,因为非常不清楚用户希望它们表示什么意思。如果有任何办法,请拒绝他们。如果您需要做出不确定的猜测,您可以尝试将 SHORT_IDS
作为第二个参数添加到 ZoneId.of()
:
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(timeZoneId, ZoneId.SHORT_IDS));
祈祷吧,试试看:
test("EST");
test("PST");
test("EET");
2021-03-26T15:55:15.225727-05:00
2021-03-26T13:55:15.363421-07:00[America/Los_Angeles]
2021-03-26T22:55:15.367676+02:00[EET]
至少结果是 100% 记录在案且可重现的,并且与语言环境和默认时区无关。所以如果用户想要别的东西,应该可以改变它。
如果你需要toString
结果并解析回来,ZonedDateTime
也可以稳定地做到这一点。并且没有任何格式化程序。并且独立于语言环境和默认时区。例如:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/Atikokan"));
System.out.println("Original: " + zdt);
String asString = zdt.toString();
ZonedDateTime parsedBack = ZonedDateTime.parse(asString);
System.out.println("Parsed back: " + parsedBack);
Original: 2021-03-26T16:00:27.867880-05:00[America/Atikokan]
Parsed back: 2021-03-26T16:00:27.867880-05:00[America/Atikokan]
如果您不可或缺地需要解析 Date.toString()
的输出,无论这种尝试有多么不确定,请参阅底部的第二个 link。那里的好答案似乎将 EST 解释为 America/New_York,将 PST 解释为 America/Los_Angeles,将 EET 解释为 Europe/Bucharest。
链接
- Oracle tutorial: Date Time 解释如何使用 java.time.
此代码示例使用 3 个时区(EST、PST、EET)。 对于每个时区,都会创建一个 Date 对象,并且 toString() 是 运行 打印出正在使用的格式。 然后将这个相同的字符串值传递给构造函数并用于创建新的日期对象。 该代码执行 运行 检查以确保所使用的时区有效。
所有 3 个时区(EST、PST、EET)均有效,但在创建对象时,仅针对 EET 返回 java.lang.IllegalArgumentException。
import java.util.*;
import java.text.*;
public class DateTest
{
public static void main (String[] args)
{
System.out.println("=======Test 1 : using EST=======");
isValidTimeZone("EST");
TimeZone.setDefault(TimeZone.getTimeZone("EST"));
runTest();
System.out.println("=======Test 2 : using PST=======");
isValidTimeZone("PST");
TimeZone.setDefault(TimeZone.getTimeZone("PST"));
runTest();
System.out.println("=======Test 3 : using EET=======");
isValidTimeZone("EET");
TimeZone.setDefault(TimeZone.getTimeZone("EET"));
runTest();
}
private static void isValidTimeZone(String tz)
{
String[] validIDs = TimeZone.getAvailableIDs();
boolean validTZ = false;
for (String str : validIDs) {
if (str != null && str.equals(tz)) {
validTZ = true;
break;
}
}
if (validTZ)
{
System.out.println(tz + " is a Valid Time Zone");
}
else
{
System.out.println(tz + " is **NOT** a Valid Time Zone");
}
}
private static void runTest()
{
try
{
String myDateString = new Date().toString();
System.out.println(" Default Date String : " + myDateString);
MyObjectWithADate myObject = new MyObjectWithADate(new Date(myDateString));
}
catch(Exception e)
{
System.out.println(" Object NOT Created!!!!!");
e.printStackTrace(System.out);
}
}
}
public MyObjectWithADate (Date eventDate)
{
System.out.println(" Passed in Date : " + eventDate.toString());
// this.eventDate = eventDate;
try {
this.eventDate = DateFormat.getInstance().parse(eventDate.toString());
System.out.println(" Object Created");
} catch (ParseException e) {
System.out.println(" Object NOT Created");
e.printStackTrace();
}
}
}
这是输出。
基于 Java 11 文档,它确实评论说 Date 已被弃用,应该使用 DateFormat.parse()。
作为测试,对象的代码被修改为使用 DateFormat.parse,但这只会让事情变得更糟。
public MyObjectWithADate (Date eventDate)
{
System.out.println(" Passed in Date : " + eventDate.toString());
// this.eventDate = eventDate;
try {
this.eventDate = DateFormat.getInstance().parse(eventDate.toString());
System.out.println(" Object Created");
} catch (ParseException e) {
System.out.println(" Object NOT Created");
e.printStackTrace();
}
}
}
这是新的结果。
问题 1 : JVM从哪个环境变量获取时区?
问题 2 : 使用原始代码,为什么使用与JVM提供的格式相同的格式时会出现异常?
问题 3 : EET 具体是什么导致它在 EST 和 PST 上失败并且可以毫无问题地交换?
问题 4 : 如果我想让任何时区的任何人都可以使用原始代码 运行,需要更改什么?
编辑添加以下内容:
以上代码是按比例缩小的模型。不幸的是,无法在所有地方修改实际代码以更改使用 Date 对象。
我使用 MyObjectWithADate 对象中的 SimpleDateFormat 做了 运行 另一个测试。这再次适用于 EST 和 PST,但不适用于 EET。
class MyObjectWithADate
{
private Date eventDate;
public MyObjectWithADate (Date eventDate)
{
System.out.println(" Passed in Date : " + eventDate.toString());
String datePattern = new String ("E MMM dd HH:mm:ss z yyyy");
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
try {
this.eventDate = simpleDateFormat.parse(eventDate.toString());
System.out.println(" Object Created");
} catch (ParseException e) {
System.out.println(" Object NOT Created");
e.printStackTrace();
}
System.out.println(" Object Created");
}
}
我开始觉得我原来的问题应该是,如何取下面的字符串
3 月 26 日星期五 21:42:522021 年东部时间
并将其放入日期对象中。
问题一:
这里是相关的doc
Gets the default TimeZone of the Java virtual machine. If the cached default TimeZone is available, its clone is returned. Otherwise, the method takes the following steps to determine the default time zone.
- Use the user.timezone property value as the default time zone ID if it's available.
- Detect the platform time zone ID. The source of the platform time zone and ID mapping may vary with implementation.
- Use GMT as the last resort if the given or detected time zone ID is unknown.
问题 2、3 和 4:
当您使用已弃用的 new Date(myString)
函数时,会抛出 EET 异常。我不确定这种方法的内部工作原理。但是为什么要打扰呢?它被弃用是有原因的。
如果您想从输入字符串创建日期对象。 Whosebug 上已经有大量关于此的答案。无论如何你真的不需要使用 new Date(string)
。这里有两个快速解决方案来获得你想要的东西。我假设您希望将日期字符串格式化为 java.util.Date
将打印出来的格式。如果这不准确,请使用 this link 创建您自己的格式。
1.使用 java.util.Date
(旧的,最好避免使用):
SimpleDateFormat oldJavaDateFormat = new SimpleDateFormat("EEE LLL dd HH:mm:ss z yyyy");
TimeZone.setDefault(TimeZone.getTimeZone("EET"));
//Surround with try/catch or throw
Date eventDate = oldJavaDateFormat.parse(new Date().toString());
//or if you need a date from some given date string
oldJavaDateFormat.parse("Thu Jan 13 15:13:13 EET 2033");
结果:
Fri Mar 26 20:52:40 EET 2021
2。使用新的java.time
(首选):
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE LLL dd HH:mm:ss z yyyy");
ZonedDateTime eventDate = ZonedDateTime.parse(new Date().toString(), formatter).withZoneSameLocal(ZoneId.of("EET"));
//or directly from a string
eventDate = ZonedDateTime.parse("Thu Jan 13 15:13:13 EET 2033", formatter);
结果:
2021-03-26T20:52:40+02:00[EET]
或者对于第二种情况(给定的字符串):
2033-01-13T15:13:13+02:00[Europe/Bucharest]
编辑:
使用上面的第一个解决方案,需要注意时区。在 SimpleDateFormat
对象上调用 parse()
可能无法按预期工作。您可能会丢失时区信息。
EST、PST 和 EET 不是时区
- EST是东部标准时间的缩写,又可以指澳大利亚东部标准时间和北美东部标准时间。
- 北美大部分地区在标准时间使用 EST,在夏令时 (DST) 使用东部夏令时 (EDT),这是一年中的大部分时间。所以这个意义上的EST可以看作是半个时区。
- 同样在澳大利亚的一些时区,一年中的大部分时间都使用 EST、EDT 或 AEDT。
- PST 可能是皮特凯恩标准时间、太平洋标准时间和菲律宾标准时间的缩写。 北美使用太平洋标准时间的所有 个地方目前都在太平洋夏令时。
- EET 可能没有歧义,可能只是指东欧时间,这是几个时区的通用名称,其中大部分时间在一年中的大部分时间都在东欧夏令时。
有效时区 Java
在 Java 中,您应该使用 Australia/Sydney、Pacific/Pitcairn 和 Europe/Bucharest 等时区 ID。总是 region/city 格式。它们表示明确的实时时区。在某些情况下,您可能能够说服 Java 将三个字母的缩写解释为时区,但由于它们经常是模棱两可的,而且通常不是真正的时区,因此不鼓励这样做。此外,当被识别为时区 ID 时,它们将被弃用。
要确定 Java 是否将给定的时区 ID 识别为有效,请使用来自 java.time 的 ZoneId
class、现代 Java 日期和时间 API,及其 of
方法。例如:
try {
ZoneId.of("EST");
System.out.println("EST is a valid time zone");
} catch (ZoneRulesException zre) {
System.out.println("EST is *not* a valid time zone");
}
输出:
EST is *not* a valid time zone
这会告诉您 Australia/Sydney、Pacific/Pitcairn、Europe/Bucharest 和 EET 都是有效时区。它还会告诉您 PST 不是。
为了与使用不推荐使用的时区缩写的旧代码一起使用,ZoneId
通过其 SHORT_IDS
常量对其中某些缩写提供额外支持。
System.out.println("" + ZoneId.SHORT_IDS.containsKey("EST")
+ " -> " + ZoneId.SHORT_IDS.get("EST"));
System.out.println("" + ZoneId.SHORT_IDS.containsKey("PST")
+ " -> " + ZoneId.SHORT_IDS.get("PST"));
System.out.println("" + ZoneId.SHORT_IDS.containsKey("EET")
+ " -> " + ZoneId.SHORT_IDS.get("EET"));
true -> -05:00 true -> America/Los_Angeles false -> null
我们注意到,EST 全年都被理解为北美东部标准时间,而 PST
在标准时间期间被理解为北美太平洋标准时间,在夏季被理解为太平洋夏令时。 EET 在没有 SHORT_IDS
的情况下得到支持,因此此处不再赘述。
为什么您观察到令人惊讶的结果
Date.toString()
打印的缩写与 ZoneId
和 TimeZone
识别的缩写不同。您注意到当 PST
被设置为默认时区时,PDT
被打印为 Date
。编辑:另一个例子:PRC 是一个已弃用的时区 ID。 TimeZone
认得。 Date
将其打印为 CST
。 PRC 代表中华人民共和国。 CST Date
表示中国标准时间,而 TimeZone
将 CST
理解为北美中部标准时间。
被弃用的 Date(String)
构造函数识别的唯一时区是 GMT、UT、UTC、EST、CST、MST、PST、EDT、CDT、MDT 和 PDT。这解释了为什么 EET
不起作用。 我相信这可以回答您的问题 2. 和 3.
SimpleDateFormat
识别的时区缩写是另一回事。它们是特定于区域设置的,因为对于给定的时区,每个区域设置可能都有自己的 abbreviation/s。没有记录如何解释不明确的时区缩写,但已知它不稳定。在不同的 Java 安装中观察到相同缩写的不同结果。
最后,DateFormat.getInstance()
期望(或生成)的语法也是特定于语言环境的,所以我不希望它能识别您的任何字符串。它也没有在您的代码中。例如,在我的语言环境中 DateFormat.getInstance()
需要一个类似于 "27/03/2021 15.04"
的字符串。
无论如何,我建议您忘记 classes TimeZone
、Date
、SimpleDateFormat
和 DateFormat
。它们的设计都很糟糕,而且早已过时。我建议您将此作为问题 4 的部分答案。
动态设置 JVM 的默认时区也是非常危险的。此更改会影响您的程序的所有部分以及同一 JVM 中 运行 的其他程序,因此您可能会遇到难以追踪到您的代码的意外风险。我建议你不要。
问题 4 : 如果我想允许任何时区的任何人 运行 原始代码,需要更改什么?
首先,我建议您对所有日期和时间工作使用 java.time。
如果您可以控制使用哪些时区 ID:
public static void test(String timeZoneId) {
try {
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(timeZoneId));
System.out.println(now);
} catch (ZoneRulesException zre) {
System.out.println("Not a valid time zone ID: " + timeZoneId);
}
}
试试看:
test("Australia/Sydney");
test("Pacific/Pitcairn");
test("Europe/Bucharest");
2021-03-27T07:49:27.095653+11:00[Australia/Sydney] 2021-03-26T12:49:27.100300-08:00[Pacific/Pitcairn] 2021-03-26T22:49:27.101219+02:00[Europe/Bucharest]
如果您需要适应已弃用的时区缩写,我非常不确定该建议什么,因为非常不清楚用户希望它们表示什么意思。如果有任何办法,请拒绝他们。如果您需要做出不确定的猜测,您可以尝试将 SHORT_IDS
作为第二个参数添加到 ZoneId.of()
:
ZonedDateTime now = ZonedDateTime.now(ZoneId.of(timeZoneId, ZoneId.SHORT_IDS));
祈祷吧,试试看:
test("EST");
test("PST");
test("EET");
2021-03-26T15:55:15.225727-05:00 2021-03-26T13:55:15.363421-07:00[America/Los_Angeles] 2021-03-26T22:55:15.367676+02:00[EET]
至少结果是 100% 记录在案且可重现的,并且与语言环境和默认时区无关。所以如果用户想要别的东西,应该可以改变它。
如果你需要toString
结果并解析回来,ZonedDateTime
也可以稳定地做到这一点。并且没有任何格式化程序。并且独立于语言环境和默认时区。例如:
ZonedDateTime zdt = ZonedDateTime.now(ZoneId.of("America/Atikokan"));
System.out.println("Original: " + zdt);
String asString = zdt.toString();
ZonedDateTime parsedBack = ZonedDateTime.parse(asString);
System.out.println("Parsed back: " + parsedBack);
Original: 2021-03-26T16:00:27.867880-05:00[America/Atikokan] Parsed back: 2021-03-26T16:00:27.867880-05:00[America/Atikokan]
如果您不可或缺地需要解析 Date.toString()
的输出,无论这种尝试有多么不确定,请参阅底部的第二个 link。那里的好答案似乎将 EST 解释为 America/New_York,将 PST 解释为 America/Los_Angeles,将 EET 解释为 Europe/Bucharest。
链接
- Oracle tutorial: Date Time 解释如何使用 java.time.