在SimpleDateFormat上使用DateTimeFormatter



我正在重构一些代码,并试图区分正在解决的问题。formatDateRfc1123的作用是显而易见的,但添加的代码的附加值是什么?

在第一次提交中,这是一个函数,它可能会因我未知的原因崩溃:

public static String formatDateRfc1123(final Date timestamp) {
SimpleDateFormat formatRf1123 = new SimpleDateFormat(RFC_1123);
formatRf1123.setTimeZone(GMT_ZONE);
return formatRfc1123.format(timestamp);
} 

后来,它被重构以解决崩溃:

public static String formatDateRfc1123(final Date timestamp, final int buildVersion) {
if (buildVersion >= Build.VERSION_CODE_O) {
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(RFC_1123, US);
Instant instant = Instant.ofEpochSecond(TimeUnit.MILLISECONDS.toSeconds(timestamp.getTime());
ZoneId zoneId = ZoneId.of(GMT_ZONE.getID());
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, zoneId);
return dateTimeFormatter.format(zonedDateTime);
} else {
SimpleDateFormat formatRf1123 = new SimpleDateFormat(RFC_1123);
formatRf1123.setTimeZone(GMT_ZONE);
return formatRfc1123.format(timestamp);
}
} 

有一个旧的用户故事链接到添加的代码,但它只链接到删除的Fabric崩溃日志。所以,我只知道它会崩溃,而不知道抛出了什么异常值。

它可能崩溃的价值和SDK版本是什么?

使用java.time的代码的前三行过于复杂,使计算容易出错。我建议您使用开箱即用的常量,以避免任何类型的歧义和错误。以下是推荐的方法:

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Date;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
// Test
System.out.println(formatDateRfc1123(new Date()));
}
public static String formatDateRfc1123(final Date timestamp) {
// Use the out-of-the-box formatter
DateTimeFormatter dateTimeFormatter = DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(Locale.US);
// Use Date#toInstant to convert it into Instant
Instant instant = timestamp.toInstant();
// Use the out-of-the-box constant for UTC (or GMT)
ZoneId zoneId = ZoneOffset.UTC;
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(instant, zoneId);
// ZonedDateTime zonedDateTime = instant.atZone(zoneId); //This is simpler
return dateTimeFormatter.format(zonedDateTime);
}
}

请注意,表示时区的三个字母的字符串很容易出错。您应该始终使用时区的全名,即Continent/City。下面给出了一个例子来演示它

import java.time.ZoneId;
public class Main {
public static void main(String[] args) {
ZoneId zoneId = ZoneId.of("EDT");
// ...
}
}

输出:

Exception in thread "main" java.time.zone.ZoneRulesException: Unknown time-zone ID: EDT
at java.base/java.time.zone.ZoneRulesProvider.getProvider(ZoneRulesProvider.java:279)
at java.base/java.time.zone.ZoneRulesProvider.getRules(ZoneRulesProvider.java:234)
at java.base/java.time.ZoneRegion.ofId(ZoneRegion.java:120)
at java.base/java.time.ZoneId.of(ZoneId.java:408)
at java.base/java.time.ZoneId.of(ZoneId.java:356)
at Main.main(Main.java:5)

SimpleDateFormat甚至不会抛出异常并以UTC(或GMT(静默格式设置日期时间。真危险!

不正确:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
sdf.setTimeZone(TimeZone.getTimeZone("EDT"));
System.out.println(sdf.format(new Date()));
}
}

输出:

2020-12-05T01:36:48Z

正确:

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
System.out.println(sdf.format(new Date()));
}
}

输出:

2020-12-04T20:36:05-05:00

请注意,java.util的日期时间API及其格式API、SimpleDateFormat已过时且为错误产品。建议完全停止使用它们,并切换到现代日期时间API。有关现代日期时间API的更多信息,请访问跟踪:日期时间

注意:如果您正在为Android项目工作,并且您的Android API级别仍然不符合Java-8,请检查通过desugaring和如何在Android项目中使用ThreeTenABP提供的Java 8+API。

相关内容

  • 没有找到相关文章

最新更新