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以来,支持选项
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,ispublic 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。我会更正我的帖子。