import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Date;
public class Test001 {
public static void main(String[] args) {
Date dt = new Date();
LocalDateTime localDateTime = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS zzz").withZone(ZoneId.of("America/New_York"));
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS zzz");
System.out.println(formatter.format(localDateTime));
System.out.println(sdf.format(dt));
}
}
2016-04-19 11:25:34.917 ET
2016-04-19 11:25:34.637 EDT
我的笔记本电脑的时区是" America / New York" (即美国东部时间/加拿大)。
我想知道如何获得" EDT"而不是" ET"使用DateTimeFormatter
。
我也想知道:为什么DateTimeFormatter
在解析/格式模式方面与SimpleDataFormat
不兼容(因为这个例子显示它们不兼容)。
答案 0 :(得分:9)
您看到的格式“ET”在Unicode Locale Data Markup Language (LDML)中称为“通用非位置”格式。您想要的格式“EDT”被称为“特定的非位置”格式。
DateTimeFormatterBuilder
中的相关源代码检查日期时间对象是否可以提供ChronoField.INSTANT_SECONDS
。如果可以,则使用“特定非位置”格式,否则使用“通用非位置”格式。
由于您要格式化不支持ChronoField.INSTANT_SECONDS
访问权限的LocalDateTime
,因此您将获得“通用非位置”格式。要获得所需的输出,请改用ZonedDateTime
或OffsetDateTime
。 (需要立即确定是夏季还是冬季。)
请注意SimpleDateFormat
和DateTimeFormatter
确实不同,假设模式相同是不正确的。决定将DateTimeFormatter
与LDML规范重新同步,这将在未来带来好处。
这个答案提供了解决方案和解释,但是我必须注意JDK代码在这里过于苛刻。由于您同时提供LocalDateTime
和ZoneId
,因此代码应该能够做得更好,并在运行中确定ChronoField.INSTANT_SECONDS
,从而使用“特定的非位置”格式。因此,我认为这里有一个边缘情况JDK issue。
答案 1 :(得分:5)
你不应该在LocalDateTime
上操作。 (几乎)等同于Date
是Instant
。您希望格式化Instant
,就像它在您的时区中一样。所以
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS zzz").withZone(ZoneId.of("America/New_York"));
Instant now = Instant.now();
System.out.println(formatter.format(now));
打印
2016-04-19 12:07:57.684 EDT
或者,您可以使用ZonedDateTime
而无需为ZoneId
DateTimeFormatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS zzz");
ZonedDateTime now = ZonedDateTime.now(ZoneId.of("America/New_York")))
System.out.println(formatter.format(now));
也打印
2016-04-19 12:11:01.667 EDT
我没有关于为什么这一切都有效的文档,但要点是这些时间(你正在尝试格式化的日期对象)有偏移,它们有区域规则,可以是日光是否节省时间。格式化程序在其打印中使用它。
LocalDateTime
没有偏移量或时区。您的格式化程序会覆盖它,但偏移量不是夏令时。
答案 2 :(得分:-2)
最直接的方法(也可能导致夏季/冬季时间的一些问题如下:
public static void main(String[] args) {
Date dt = new Date();
LocalDateTime localDateTime = LocalDateTime.now();
String dateFormat;
if (Calendar.getInstance().get(Calendar.DST_OFFSET) != 0) {
dateFormat = "yyyy-MM-dd HH:mm:ss.SSS 'EDT'";
} else {
dateFormat = "yyyy-MM-dd HH:mm:ss.SSS 'EST'";
}
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(dateFormat).withZone(ZoneId.of("America/New_York"));
SimpleDateFormat sdf = new SimpleDateFormat(dateFormat);
System.out.println(formatter.format(localDateTime));
System.out.println(sdf.format(dt));
}