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

bkkx9g8r  于 2023-05-12  发布在  Java
关注(0)|答案(3)|浏览(115)

我想检查我的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;
}

但是使用异常作为返回值是一种不好的做法,而且性能代价很高。
有没有其他简单又好的方法来做这件事?

bbmckpt7

bbmckpt71#

如果查看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;
}
xam8gpfp

xam8gpfp2#

使用异常作为返回值是不好的做法,而且性能代价很高。
这是一个很好的观点,值得寻找替代方案,但在某些情况下,这只是提供的API。通常对于解析来说,你确实需要一个异常,因为解析失败是 exceptional 的情况--你期望值被解析,只需要考虑它不被解析的可能性。
在这种情况下,我只是像你一样捕获异常。

lf5gs5x2

lf5gs5x23#

我在junit5中使用的测试代码片段
assertDoesNotThrow(() -> ZonedDateTime.parse("invalid zoned datetime"));

相关问题