pet*_*rov 10 java java-8 java-time
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));
}
}
Run Code Online (Sandbox Code Playgroud)
2016-04-19 11:25:34.917 ET
2016-04-19 11:25:34.637 EDT
Run Code Online (Sandbox Code Playgroud)
我的笔记本电脑的时区是"美国/纽约"(即东部时间美国/加拿大).
我想知道如何使用"EDT"代替"ET" DateTimeFormatter
.
我也想知道:为什么在解析/格式模式方面DateTimeFormatter
不兼容SimpleDataFormat
(因为这个例子表明它们不兼容).
Jod*_*hen 10
您看到的格式"ET"在Unicode区域设置数据标记语言(LDML)中称为"通用非位置"格式.您想要的格式"EDT"称为"特定非位置"格式.
DateTimeFormatterBuilder
检查相关的源代码以查看日期时间对象是否可以提供ChronoField.INSTANT_SECONDS
.如果可以,则使用"特定非位置"格式,如果不是,则使用"通用非位置"格式.
由于您正在格式化a LocalDateTime
,它不支持访问ChronoField.INSTANT_SECONDS
,因此您将获得"通用非位置"格式.要获得所需的输出,请使用ZonedDateTime
或OffsetDateTime
替代.(需要立即确定是夏季还是冬季.)
注意SimpleDateFormat
并且DateTimeFormatter
确实不同,假设模式相同是不正确的.决定DateTimeFormatter
与LDML规范重新同步,这将在未来带来好处.
这个答案提供了解决方案和解释,但是我必须注意JDK代码在这里过于苛刻.由于您同时提供a LocalDateTime
和a ZoneId
,因此代码应该能够做得更好,并在运行中确定ChronoField.INSTANT_SECONDS
,从而使用"特定的非位置"格式.因此,我认为这里有一个边缘案例JDK问题.
你不应该操作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));
Run Code Online (Sandbox Code Playgroud)
打印
2016-04-19 12:07:57.684 EDT
Run Code Online (Sandbox Code Playgroud)
或者,您可以使用a 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));
Run Code Online (Sandbox Code Playgroud)
还打印
2016-04-19 12:11:01.667 EDT
Run Code Online (Sandbox Code Playgroud)
我没有关于为什么这一切都有效的文档,但要点是这些时间(你试图格式化的日期对象)有偏移,它们有区域规则,可以是夏令时或不是.格式化程序在其打印中使用它.
A LocalDateTime
没有偏移量或时区.您的格式化程序会覆盖它,但偏移量不是夏令时.
uni*_*now -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));
}
Run Code Online (Sandbox Code Playgroud)