How to differentiate when "second field" is missing in LocalDateTime
Asked Answered
I

3

5

I am given LocalDateTime object created from String. I want to check whether that original string has "seconds" parameter or not. My two inputs are:

String a = "2016-06-22T10:01"; //not given
String b = "2016-06-22T10:01:00"; //not given

LocalDateTime dateA = LocalDateTime.parse(a, DateTimeFormatter.ISO_DATE_TIME);
LocalDateTime dateB = LocalDateTime.parse(b, DateTimeFormatter.ISO_DATE_TIME);

Problem is I am given dateA and dateB, not a and b.

I have tried various ways like converting LocalDateTime to String and finding its length. For that I used two approaches.

date.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME).length();
date.toString().length();

But first approach gives length 19 for both dateA and dateB whereas second approach gives length 16 for both dateA and dateB.

I am unable to find any way to differentiate dateA and dateB.

Internal answered 23/6, 2017 at 8:2 Comment(1)
There is actually no difference between these LocalDateTimes, since missing seconds mean that they're zero.Gardening
M
4

As other people have already said, a LocalDateTime-object has always a second part. The other question is if the original input has got a second part or not. It is possible to find out the answer with only Java-8-means (but it is ugly because it is based on exception control flow):

String a = "2016-06-22T10:01"; // not given
String b = "2016-06-22T10:01:00"; // given

boolean hasSecondPart;
try {
    TemporalAccessor tacc =
        DateTimeFormatter.ISO_DATE_TIME.parseUnresolved(a, new ParsePosition(0));
    tacc.get(ChronoField.SECOND_OF_MINUTE);
    hasSecondPart = true;
} catch (UnsupportedTemporalTypeException ex) {
    hasSecondPart = false;
}
System.out.println(hasSecondPart); // true for input b, false for input a

Side note:

An exception-free check if the string input has a second part or not would be possible with my library Time4J using this code:

boolean hasSecondPart =
    Iso8601Format.EXTENDED_DATE_TIME.parseRaw(a).contains(PlainTime.SECOND_OF_MINUTE);
Moitoso answered 23/6, 2017 at 11:35 Comment(0)
C
2

In ISO_DATE_TIME, seconds are optional (and set to zero if not present), that's why it parses both inputs. And LocalDateTime.toString() method will print the seconds only if it's not zero.

So, once you have the LocalDateTime objects created, you can't know if the original String had the seconds field.


To validate if the seconds field is present in the input String, you must create your own pattern and check if it throws exception when parsing:

// formatter with required seconds
DateTimeFormatter withSecs = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");

LocalDateTime.parse(b, withSecs); // OK
LocalDateTime.parse(a, withSecs); // DateTimeParseException

If you want just to check if the field is present, but don't want to build a LocalDateTime object, you can also use parseUnresolved method, which doesn't throw exceptions:

ParsePosition position = new ParsePosition(0);
withSecs.parseUnresolved(a, position);
if(position.getErrorIndex() == -1) {
    System.out.println("No error (it contains seconds)"); // b gets here
} else {
    System.out.println("Error (it does not contain seconds)"); // a gets here
}
Cloche answered 23/6, 2017 at 10:27 Comment(1)
Yes, it works with a fixed pattern, but if the pattern has an optional part (like used in DateTimeFormatter.ISO_DATE_TIME) then the method parseUnresolved() would only do a syntactical check of the pattern and always says: no error. In case of optional parts: Only testing by get(ChronoField.SECOND_OF_MINUTE) finally helps.Moitoso
N
1

In Java 8 DateTime API dates can be represented in the following way:

As you can see, there is no way to differentiate between year-month-day-hour-minute-second and year-month-day-hour-minute. So, after the conversion from String to LocalDateTime is done - you can't differentiate it. The only way to do this is with String (either by length or regex), not with LocalDateTime object.

Nide answered 23/6, 2017 at 10:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.