到目前为止给出的所有答案都表明你必须忍受异常捕获,但有一些方法可以避免异常.我演示了两种方法,一种使用内置的SimpleDateFormat-API,另一种使用我的库
Time4J.
的SimpleDateFormat
private static final List SDF_FORMATS;
static {
String[] formats =
{
"yyyy-MM-dd'T'HH:mm:ss.SSSX",
"yyyy-MM-dd'T'HH:mm:ss.SSS-HH:mm",
"EEE MMM dd HH:mm:ss Z yyyy"
};
SDF_FORMATS =
Arrays.stream(formats)
.map(pattern -> new SimpleDateFormat(pattern, Locale.ENGLISH))
.collect(Collectors.toList());
}
public static java.util.Date parse(String input) {
for (SimpleDateFormat sdf : SDF_FORMATS) {
ParsePosition pos = new ParsePosition(0);
java.util.Date d = sdf.parse(input, pos);
if (pos.getErrorIndex() == -1) {
return d;
}
}
// log an error message
return null; // or throw an exception
}
虽然与try-catch-code相比并不是非常壮观,但是可观察到的性能提升.但是,一个重要的警告是,这个代码不是线程安全的.要在多线程环境中使用,您必须始终实例化SimpleDateFormat的新实例,或者您可以尝试使用ThreadLocal来最小化此类实例化.
Time4J
private static final MultiFormatParser MULTI_FORMAT_PARSER;
static {
String[] formats =
{
"yyyy-MM-dd'T'HH:mm:ss.SSSX",
"yyyy-MM-dd'T'HH:mm:ss.SSS-HH:mm",
"EEE MMM dd HH:mm:ss Z yyyy"
};
List> formatters =
Arrays.stream(formats)
.map(pattern ->
ChronoFormatter.ofMomentPattern(
pattern,
PatternType.CLDR,
Locale.ENGLISH,
Timezone.ofSystem().getID()))
.collect(Collectors.toList());
MULTI_FORMAT_PARSER = MultiFormatParser.of(formatters);
}
public static java.util.Date parse(String input) {
ParseLog plog = new ParseLog();
Moment m = MULTI_FORMAT_PARSER.parse(input, plog);
if (plog.isError()) {
// log an error message based on plog.getErrorMessage()
return null; // or throw an exception
} else {
return TemporalType.JAVA_UTIL_DATE.from(m); // converted to old API
}
}
这种方式是迄今为止解析多种格式的最快方法.自己尝试一下(也可以使用版本行3.x在Java-6或Android上使用Time4J,但是你必须在静态初始化程序中调整Java-8-streaming代码).性能方面的改进是巨大的.代码也是线程安全的.
关于格式模式的一般评论
>我担心看到“yyyy-MM-dd’T’HH:mm:ss.SSS-hh:mm”的模式,因为“h”代表12小时制(因此AM / PM缺失! ).>我也担心看到模式“yyyy-MM-dd’T’HH:mm:ss.SSS’Z’”,因为除非你明确设置GMT-Zone(零),否则在输入中转义字面“Z”是错误的您的SimpleDateFormat实例上的offset).背景:ISO-8601定义了这样的模式,并始终将偏移UTC 00:00分配给文字“Z”.通过转义,您将获得基于错误计算的结果(无例外或警告).