Format string for java.time.format.DateTimeFormatter.ISO_INSTANT?

leeyuiwah :

In Java 8's java.time package, there is this formatter

java.time.format.DateTimeFormatter.ISO_INSTANT (JavaDoc)

which allows for optional fractional second in parsing and formatting

The ISO instant formatter that formats or parses an instant in UTC, such as '2011-12-03T10:15:30Z'.

This returns an immutable formatter capable of formatting and parsing the ISO-8601 instant format. When formatting, the second-of-minute is always output. The nano-of-second outputs zero, three, six or nine digits digits as necessary. When parsing, time to at least the seconds field is required. Fractional seconds from zero to nine are parsed. The localized decimal style is not used.

What is the format string that can be used to create this formatter? I need to store the String but not the DateTimeFormatter because the latter is not serializable.

Specifically, I want to know how to express the fractional seconds (including the . that precedes the numbers). I know S is for fraction-of-second, and X is for zone-offset, but I don't how to put them together

S       fraction-of-second          fraction          978
X       zone-offset 'Z' for zero    offset-X          Z; -08; -0830; -08:30; -083015; -08:30:15;
leeyuiwah :

I could not find the direct equivalent format pattern string. As @JB Nizet has suggest, this may not even be possible.

However, I found that I can use the optional section markers [ and ] in the String pattern to get an approximate behaviour:

"yyyy-MM-dd'T'HH:mm:ss[.SSS]X"

This can handle the following input strings:

"2019-09-02T12:38:16Z"
"2019-09-02T12:38:16.294Z"

This makes the fractional-second component optional.

However, for me there is still a limitation -- the fractional second, while now optional, must be exactly 3-digit if present. I don't know what is the String pattern that can make the DateTimeFormatter accept 0-9 fractional second digits.

To overcome this limitation, now I use the following solution -- any fractional-second component, if present, are to be first "canonicalized" into 3 digits. This is done via a method optionalCanonicalizeFractionalSecond() (code shown below) before the input string is passed into a DataTimeFormatter for parsing. This method works for me so far.

So given mm:ss[.SSS] as part of the input pattern:

`12:30.123`       will be canon'ed as `12:30.123`
`12:30.12`        will be canon'ed as `12:30.120`
`12:30.1`         will be canon'ed as `12:30.100`
`12:30.123456789` will be canon'ed as `12:30.123`

Example Code

/*
 * Apparently java.time.format.DateTimeFormatter cannot handling
 * a string pattern with variable number of fractional-second
 * digitit.  This method "canonicalize"  any such component
 * to 3 digits
 */
private String optionalCanonicalizeFractionalSecond(String input) {
    if (!formatPattern.contains("mm:ss[.SSS]")) {
        // no fractional-second component in the pattern
        return input; // no need to make any changes
    }
    Pattern regexPattern = Pattern.compile("^(.*)(\\d\\d:\\d\\d)(\\.\\d+)(.*)$");
    Matcher matcher = regexPattern.matcher(input.trim());
    if (!matcher.matches()) {
        // no fractional-second componet in the input string
        return input;
    }
    String prefix = matcher.group(1);
    String minuteSecondString = matcher.group(2);
    String fractionalSecondString = matcher.group(3);
    String suffix = matcher.group(4);
    String canonFss;
    if (fractionalSecondString.length() == 2) {
        canonFss = fractionalSecondString + "00";           // padding with 00
    } else if (fractionalSecondString.length() == 3) {
        canonFss = fractionalSecondString + "0";            // padding with 0
    } else if (fractionalSecondString.length() == 4) {
        canonFss = fractionalSecondString;                  // as is
    } else if (fractionalSecondString.length() > 4
        && fractionalSecondString.length() <= 10) {
        canonFss = fractionalSecondString.substring(0,4);   // truncate to 3 digits
    } else {
        return input;
    }
    return prefix + minuteSecondString + canonFss + suffix;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=309139&siteId=1