SimpleDateFormat 解析方法第一次起作用,第二次被忽略
SimpleDateFormat parse method works first time, is ignored second time
我有一个日期时间,我首先将其转换为当地时间,然后再转换为另一个时区。第一次转换没有问题,但第二次转换被忽略。有什么问题?
String input = "2020-05-20 01:10:05";
SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
localFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
try {
Date date = localFormat.parse(input);
System.out.println(date); //Wed May 20 01:10:05 PDT 2020 <--- Logs this (Expected)
SimpleDateFormat estFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
estFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String newDate = estFormat.format(date);
System.out.println(newDate); //2020-05-20 04:10:05 <--- Logs this (Expected)
Date dateEst = estFormat.parse(newDate);
System.out.println(dateEst); //Wed May 20 01:10:05 PDT 2020 <--- Logs this (Unexpected) Should be Wed May 20 04:10:05 EST 2020
}catch (Exception e){
e.printStackTrace();
}
似乎在尝试转换为 America/New_York
时区时忽略了第二个 estFormat.parse()
。
首先,除非您要维护遗留代码,否则不要使用 Date
。
其次,SimpleDateFormat
正确解析了日期。您没有像在上一个(正确的)示例中那样使用 estFormat
来格式化日期。尝试:
System.out.println(estFormat.format(dateEst));
This 很好地概述了 Java 中与日期相关的不同类型的实体,值得一读。以下是您可能会觉得有用的摘录:
The java.util.Date
has no concept of time zone, and only represents the number of seconds passed since the Unix epoch time – 1970-01-01T00:00:00Z. But, if you print the Date
object directly, the Date
object will be always printed with the default system time zone.
我注意到一件事,第一个变量的类型是字符串,第二个变量的类型是日期。所以可能类型转换在这里造成了问题。没有什么比忽略第二次更好的了。
java.time
我强烈建议您使用 java.time,现代 Java 日期和时间 API,作为您的日期和时间工作。一旦习惯了稍微不同的思维方式,您可能还会发现生成的代码更清晰、更自然。我们先把常量的东东定义为常量:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
private static final ZoneId FROM_ZONE = ZoneId.of("America/Los_Angeles");
private static final ZoneId TO_ZONE = ZoneId.of("America/New_York");
有了这些我们就可以做我们的工作了:
String input = "2020-05-20 01:10:05";
ZonedDateTime fromDateTime
= LocalDateTime.parse(input, FORMATTER).atZone(FROM_ZONE);
System.out.println("From: " + fromDateTime);
ZonedDateTime toDateTime = fromDateTime.withZoneSameInstant(TO_ZONE);
System.out.println("To: " + toDateTime);
String formatted = toDateTime.format(FORMATTER);
System.out.println("Formatted: " + formatted);
输出为:
From: 2020-05-20T01:10:05-07:00[America/Los_Angeles]
To: 2020-05-20T04:10:05-04:00[America/New_York]
Formatted: 2020-05-20 04:10:05
编辑:
How would I get it to have EST 2020
at the end?
对于大多数用途来说,一个不错的选择是使用本地化格式化程序:
private static final DateTimeFormatter TARGET_FORMATTER
= DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(Locale.US);
像这样:
String formatted = toDateTime.format(TARGET_FORMATTER);
Formatted: May 20, 2020 at 4:10:05 AM EDT
一个细节,我们最后没有得到 EST,因为纽约和北美东海岸的大部分地区使用夏令时 (DST),因此在 5 月是东部夏令时 EDT。
出了什么问题?
您似乎希望 Date
对象携带解析它的格式化程序的时区 America/New_York。老式的 Date
对象无法做到这一点。这只是一个愚蠢的时间点,没有任何时区或其他附加信息。令许多人感到困惑的是,它的 toString
方法使用 JVM 的默认时区来呈现返回的字符串,从而给人一种时区存在的错误印象。相比之下,现代 ZonedDateTime
,顾名思义,确实拥有一个时区。
Link
Oracle tutorial: Date Time 解释如何使用 java.time.
我有一个日期时间,我首先将其转换为当地时间,然后再转换为另一个时区。第一次转换没有问题,但第二次转换被忽略。有什么问题?
String input = "2020-05-20 01:10:05";
SimpleDateFormat localFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
localFormat.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault()));
try {
Date date = localFormat.parse(input);
System.out.println(date); //Wed May 20 01:10:05 PDT 2020 <--- Logs this (Expected)
SimpleDateFormat estFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
estFormat.setTimeZone(TimeZone.getTimeZone("America/New_York"));
String newDate = estFormat.format(date);
System.out.println(newDate); //2020-05-20 04:10:05 <--- Logs this (Expected)
Date dateEst = estFormat.parse(newDate);
System.out.println(dateEst); //Wed May 20 01:10:05 PDT 2020 <--- Logs this (Unexpected) Should be Wed May 20 04:10:05 EST 2020
}catch (Exception e){
e.printStackTrace();
}
似乎在尝试转换为 America/New_York
时区时忽略了第二个 estFormat.parse()
。
首先,除非您要维护遗留代码,否则不要使用 Date
。
其次,SimpleDateFormat
正确解析了日期。您没有像在上一个(正确的)示例中那样使用 estFormat
来格式化日期。尝试:
System.out.println(estFormat.format(dateEst));
This 很好地概述了 Java 中与日期相关的不同类型的实体,值得一读。以下是您可能会觉得有用的摘录:
The
java.util.Date
has no concept of time zone, and only represents the number of seconds passed since the Unix epoch time – 1970-01-01T00:00:00Z. But, if you print theDate
object directly, theDate
object will be always printed with the default system time zone.
我注意到一件事,第一个变量的类型是字符串,第二个变量的类型是日期。所以可能类型转换在这里造成了问题。没有什么比忽略第二次更好的了。
java.time
我强烈建议您使用 java.time,现代 Java 日期和时间 API,作为您的日期和时间工作。一旦习惯了稍微不同的思维方式,您可能还会发现生成的代码更清晰、更自然。我们先把常量的东东定义为常量:
private static final DateTimeFormatter FORMATTER
= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ROOT);
private static final ZoneId FROM_ZONE = ZoneId.of("America/Los_Angeles");
private static final ZoneId TO_ZONE = ZoneId.of("America/New_York");
有了这些我们就可以做我们的工作了:
String input = "2020-05-20 01:10:05";
ZonedDateTime fromDateTime
= LocalDateTime.parse(input, FORMATTER).atZone(FROM_ZONE);
System.out.println("From: " + fromDateTime);
ZonedDateTime toDateTime = fromDateTime.withZoneSameInstant(TO_ZONE);
System.out.println("To: " + toDateTime);
String formatted = toDateTime.format(FORMATTER);
System.out.println("Formatted: " + formatted);
输出为:
From: 2020-05-20T01:10:05-07:00[America/Los_Angeles] To: 2020-05-20T04:10:05-04:00[America/New_York] Formatted: 2020-05-20 04:10:05
编辑:
How would I get it to have
EST 2020
at the end?
对于大多数用途来说,一个不错的选择是使用本地化格式化程序:
private static final DateTimeFormatter TARGET_FORMATTER
= DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG)
.withLocale(Locale.US);
像这样:
String formatted = toDateTime.format(TARGET_FORMATTER);
Formatted: May 20, 2020 at 4:10:05 AM EDT
一个细节,我们最后没有得到 EST,因为纽约和北美东海岸的大部分地区使用夏令时 (DST),因此在 5 月是东部夏令时 EDT。
出了什么问题?
您似乎希望 Date
对象携带解析它的格式化程序的时区 America/New_York。老式的 Date
对象无法做到这一点。这只是一个愚蠢的时间点,没有任何时区或其他附加信息。令许多人感到困惑的是,它的 toString
方法使用 JVM 的默认时区来呈现返回的字符串,从而给人一种时区存在的错误印象。相比之下,现代 ZonedDateTime
,顾名思义,确实拥有一个时区。
Link
Oracle tutorial: Date Time 解释如何使用 java.time.