检查datetime字符串是否可以转换为ZonedDateTime

时间:2018-01-11 19:49:14

标签: java

我想检查一下String是否可转换为ZonedDateTime

 String datetime = "2018-01-11T21:32:10.876+02:00"; // valid
 String badDateTime = "blah blah"; //not valid

我考虑过用this regex检查一下,但由于私人原因,这对我来说不是一个相关的解决方案。

我还考虑过以这种方式使用try..catch

public void testing() {
    String datetime = "2018-01-11T21:32:10.876+02:00";

    System.out.println(isDateTime("no")); // false
    System.out.println(isDateTime(datetime)); // true
}


private boolean isDateTime(String str){
    boolean checkDateTimeString;

    try {
        ZonedDateTime.parse(str);
        checkDateTimeString = true;
    } catch (DateTimeParseException e){
        checkDateTimeString = false;
    }

    return checkDateTimeString;
}

但是使用例外作为返回值是不好的做法,而且性能成本很高。

有没有其他简单而好的方法来做那件事?

2 个答案:

答案 0 :(得分:2)

如果查看ZonedDateTime.parse方法实现,您会发现该方法定义如下:

public static ZonedDateTime parse(CharSequence text) {
    return parse(text, DateTimeFormatter.ISO_ZONED_DATE_TIME);
}

public static ZonedDateTime parse(CharSequence text, DateTimeFormatter formatter) {
    Objects.requireNonNull(formatter, "formatter");
    return formatter.parse(text, ZonedDateTime::from);
}

如果你也看DateTimeFormatter,你会发现一个名为parseUnresolved的方法。您可以按如下方式使用它:

DateTimeFormatter.ISO_ZONED_DATE_TIME.parseUnresolved(str, new ParsePosition(0));

传递的字符串将被解析但未解析。然后,您可以查看parseResolved0实现并执行实际解析而不会抛出异常。您将不得不使用方法返回值。

您需要的方法如下:

public TemporalAccessor parse(final CharSequence text) {
    ParsePosition pos = new ParsePosition(0);
    TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_ZONED_DATE_TIME.parseUnresolved(text, pos);
    if (temporalAccessor == null || pos.getErrorIndex() >= 0 || pos.getIndex() < text.length()) {
        return null;
    }
    return temporalAccessor;
}

请注意,返回的TemporalAccessor将无法解析。我需要更深入地查看代码才能找到它的含义。

最后,如果你想检查一个字符串是否可以被解析为ZonedDateTime而没有例外,你只需要检查返回值:

parse("2018-01-11T21:32:10.876+02:00"); //return ZonedDateTime instance
parse("blah blah"); //return null

修改

由于无法使用返回的Parsed,因此编写解析方法是“错误的”(除非TemporalAccessor公开的方法对您有用)。因此,检查有效性的方法会更正确:

public boolean isParseableAsZonedDateTime(final CharSequence text) {
    ParsePosition pos = new ParsePosition(0);
    TemporalAccessor temporalAccessor = DateTimeFormatter.ISO_ZONED_DATE_TIME.parseUnresolved(text, pos);
    if (temporalAccessor == null || pos.getErrorIndex() >= 0 || pos.getIndex() < text.length()) {
        return false;
    }
    return true;
}

答案 1 :(得分:1)

  

使用异常作为返回值是不好的做法,而且性能成本很高。

这是一个好点,值得寻找替代方案,但在某些情况下,这只是提供的API。通常,对于解析,您确实需要异常,因为解析失败是例外情况 - 您希望解析该值,并且只需考虑它没有的可能性。

在这种情况下,我只是抓住你正在做的例外。