问题描述
我将其解析为 zoneddatetime
,但在格式化时,它显示为 GMT-04:00
,而不是我期望的 EST
。
为什么会发生这种情况 - 我可以让它显示我期望的时区吗?
示例
final String dateString = "16/07/2017 19:28:33 EST";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z");
System.out.println(messageformat.format("Input - {0}",dateString));
System.out.println(messageformat.format("Parsed - {0}",formatter.format(zoneddatetime.parse(dateString,formatter))));
输出:
Input - 16/07/2017 19:28:33 EST
Parsed - 16/07/2017 19:28:33 GMT-04:00
我的时区是 GMT。采用 OpenJDK 14.0.2.12,en_GB 语言环境。
就上下文而言,我试图在 Amazon Corretto 11 的最新版本中更好地理解此问题 - https://github.com/corretto/corretto-11/issues/147
解决方法
tl;博士
你说:
它显示为 GMT-04:00,而不是我预期的 EST。
此类详细信息取决于 Locale.UK
是否有效。
-
16/07/2017 19:28:33 GMT-04:00
⇐Locale.UK
-
16/07/2017 19:28:33 EDT
⇐Locale.US
-
16/07/2017 19:28:33 HAE
⇐Locale.CANADA_FRENCH
➥ 对于文本日期时间数据交换,(a) 坚持使用 ISO 8601 标准格式,并且 (b) 尽可能使用零偏移量。这样做没有意义Issue # 147。
详情
顺便说一句,尽量避免使用 2-4 个字母的伪区域解析日期时间文本,例如 EST
、EDT
、IST
,CST
。这些是非标准的、非唯一的(!),试图暗示时区以及 Daylight Saving Time (DST) 是否有效。
仅使用 real time zones,格式为 Continent/Region
,例如 Europe/London
。
你说:
而不是我期望的 EST
夏令时 (DST) 在 America/New_York
而非 Standard Time 时区的该日期时间生效。所以你应该期待 EDT
而不是 EST
。
我建议您不要通过在 println
语句中嵌入调用来使问题复杂化。
您应该指定 Locale
而不是隐式依赖 JVM 的当前默认语言环境,该语言环境可以在运行时随时更改。所以请注意我如何将 .withLocale( locale )
附加到 DateTimeFormatter
对象的形成中。我指定了 Locale.UK
,因为您在评论中提到了 en_GB
。
那么让我们将您的代码修改为:
final Locale locale = Locale.US ; // Locale.UK versus Locale.US yield different outputs.
final String input = "16/07/2017 19:28:33 EST";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern( "dd/MM/yyyy HH:mm:ss z" ).withLocale( locale ) ;
final ZonedDateTime zdt = ZonedDateTime.parse( input,formatter ) ;
final String zdtToString = zdt.toString() ;
final String zdtFormatted = zdt.format( formatter ) ;
……和:
// Dump to console.
System.out.println( "input: " + input ) ;
System.out.println( "zdt: " + zdt ) ;
System.out.println( "zdtToString: " + zdtToString ) ;
System.out.println( "zdtFormatted: " + zdtFormatted ) ;
请参阅有关 Java 12 的 code run live at IdeOne.com。
input: 16/07/2017 19:28:33 EST
zdt: 2017-07-16T19:28:33-04:00[America/New_York]
zdtToString: 2017-07-16T19:28:33-04:00[America/New_York]
zdtFormatted: 16/07/2017 19:28:33 GMT-04:00
如果我们将该区域设置从 Locale.UK
更改为 Locale.US
,我们会得到不同的结果。
zdtFormatted: 16/07/2017 19:28:33 EDT
,
tl;博士
切勿使用没有 Locale
的日期时间解析器/格式化程序类型(类)。
import java.text.MessageFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
class Main {
public static void main(String[] args) {
final String dateString = "16/07/2017 19:28:33 EST";
final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss z",Locale.ENGLISH);
System.out.println(MessageFormat.format("Input - {0}",dateString));
System.out.println(
MessageFormat.format("Parsed - {0}",formatter.format(ZonedDateTime.parse(dateString,formatter))));
}
}
输出:
Input - 16/07/2017 19:28:33 EST
Parsed - 16/07/2017 19:28:33 EDT