Java 安全SimpleDataFormat解析

Java 安全SimpleDataFormat解析,java,try-catch,simpledateformat,Java,Try Catch,Simpledateformat,我有一小段代码,它从响应本身解析响应生成时间,并将其转换为日期,以备将来使用。事情是这样的: SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); Date responseTime = sdf.parse(RStime); Instant responseInstant = responseTime.toInstant(); Date oldfashionedDateObject = Date

我有一小段代码,它从响应本身解析响应生成时间,并将其转换为日期,以备将来使用。事情是这样的:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date responseTime = sdf.parse(RStime);
Instant responseInstant = responseTime.toInstant();
Date oldfashionedDateObject = Date.from(responseInstant);
System.out.println("Converted to old-fashioned Date: " + oldfashionedDateObject);
它几乎像一个符咒。准确地说,它在99.9%的时间内都能工作,但有一种情况除外:当毫秒部分为000时,服务器根本不追加.000毫秒,因此我们有一个问题

现在,根据if解析失败,函数返回null。然而,我可能误解了它,因为它只是抛出了一个异常

我对Java非常陌生,并尝试了catch机制,所以有谁能为处理此类情况提供一个优雅的良好实践解决方案吗

谢谢

根据您提到的
parse
方法:

公共日期解析(字符串文本,解析位置)

抛出:

NullPointerException-如果文本或pos为空

因此,一个选项是捕获该异常并在捕获中执行所需操作,例如:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
try {
  Date responseTime = sdf.parse(RStime, position);
} catch (NullPointerException e) {
  e.printStackTrace();
  //... Do extra stuff if needed
}
或从以下位置继承的方法:

公共日期解析(字符串源)

抛出:

ParseException-如果无法指定指定字符串的开头 解析


这真的是一种例外情况吗?如果不是,那么您可能不应该在这种情况下使用异常。在我看来,时间以.000ms结束是正常的。在这种情况下,您可以检查字符串是否包含
(点),如果不包含,则在末尾追加.000

if(!RStime.contains(".")){
    RStime+=".000";
}
编辑:我忘记了时间字符串中的时区。你可能需要更复杂一点的东西。像这样的东西应该可以做到:

if(!RStime.contains(".")){
    String firstPart = RStime.substring(0, 21);
    String secondPart = RStime.substring(21);
    RStime = firstPart + ".000" + secondPart;
}

您可以检查点,然后使用第一种或第二种格式:

String timeString = "2018-04-09T10:47:16.999-02:00";
//String timeString = "2018-04-09T10:47:16-02:00";
String format = timeString.contains(".") ? "yyyy-MM-dd'T'HH:mm:ss.SSSXXX" : "yyyy-MM-dd'T'HH:mm:ssXXX";
Date responseTime = new SimpleDateFormat(format).parse(timeString);
System.out.println("responseTime: " + responseTime);
如果您注释掉第一行,注释掉第二行,然后再次运行它,它将同时打印出来:

responseTime: Mon Apr 09 14:47:16 CEST 2018
顺便说一下:

  • Java 7(您显然使用的版本)返回一个
    Java.text.ParseException:不可解析的日期:“2018-04-09T10:47:16-02:00”

  • 自Java 8以来,支持选项

java.time 此代码段的输出为:

解析日期和时间:2018-04-09T10:47:16.999-02:00

它同样适用于省略了000毫秒的版本:

String rsTime = "2018-04-09T10:47:16-02:00";
解析日期和时间:2018-04-09T10:47:16-02:00

您使用的类,
SimpleDateFormat
Date
,设计不好,而且早已过时(前者特别麻烦)。因此,我不仅建议在这种情况下使用java.time,即现代java日期和时间API。但是,服务器中的字符串采用ISO 8601格式,
OffsetDateTime
和其他java.time类将此格式解析为默认格式,也就是说,不使用任何显式格式化程序,这已经使任务变得非常简单。此外,在标准中,分数秒是可选的,这就是为什么解析字符串的两个变体时没有任何问题
OffsetDateTime
还将ISO 8601从它的
toString
方法打印回来,这就是为什么在这两种情况下都会打印与解析字符串相同的字符串

只有当您需要一个旧式的
Date
对象作为您现在无法更改的遗留API时,才可以这样转换:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
Date responseTime = sdf.parse(RStime);
Instant responseInstant = responseTime.toInstant();
Date oldfashionedDateObject = Date.from(responseInstant);
System.out.println("Converted to old-fashioned Date: " + oldfashionedDateObject);
我在欧洲/哥本哈根时区的计算机上的输出为:

转换为旧式日期:2018年4月9日星期一14:47:16 CEST


链接:解释如何使用java.time。

如果您使用java 8+并希望以自己的方式处理此
null
,您可以始终创建一个返回
Optional
的方法,并使用
Optional.ofNullable(sdf.parse(stringTime))
方法创建它。如果解析器返回
null
,您的可选值将为空。此代码不编译
Date response Time=sdf.parse(RStime)
您看到的是错误类中的
parse()
方法<代码>sdf.parse(RStime)呼叫。它抛出:ParseException-如果无法解析指定字符串的开头。在将日期表示形式提供给
SimpleDataFormat.parse()
方法之前,您可能还希望规范化
string
的日期表示形式。我建议您不要使用
SimpleDataFormat
date
。这些类设计得很糟糕,而且早已过时(前者尤其是出了名的麻烦)。改为使用
OffsetDateTime
from。它还将在没有任何显式格式化程序的情况下解析字符串(有毫秒和没有毫秒)。这是不正确的<代码>sdf.parse(RStime)呼叫。它抛出:ParseException——如果指定字符串的开头无法解析,则抛出:ParseException。这是在Java 9中,我根据@Quinteger所要求的(Java 7)表示,在这种情况下,无论是Java 9还是Java 7的doc。在
simpleDataFormat
类中没有定义
parse(String)
方法。它是
DateFormat
tho.correct,is
public Date parse(String text,ParsePosition pos)
这将无法在模式'yyyy-MM-dd'T'HH:MM:ss.SSSXXX'上解析,因为它省略了我在其他注释中指出的ISO 8601时区,
parse()
这里调用的方法是来自
DateFormat
类的方法,它只接受一个参数,一个字符串。无论是在Java7中还是在任何NewerMongalen中,这个函数都没有返回null,您是正确的,谢谢。在提供的javadoc链接中,只列出了方法parse(字符串文本,ParsePosition pos),而没有方法parse(字符串文本)。我的快速查找导致错误的假设,即两者都将返回null。我会更正我的帖子。