import java.time.format.DateTimeFormatter ;
import java.time.format.DateTimeFormatterBuilder ;
import java.time.format.ResolverStyle ;
import java.time.temporal.ChronoField ;
import java.time.temporal.TemporalAccessor ;
import java.time.ZoneOffset ;
import java.time.LocalDate ;
import java.time.LocalDateTime ;
import java.time.ZonedDateTime ;
import java.time.OffsetDateTime ;
class Ideone
{
public static void main
( String [ ] args
) { try {
// Define the formatter with year as the first component, followed by month and day
DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder( )
.appendPattern ( "yyyyMMdd" ) ; // Year, Month, Day are now the base mandatory components
// Make subsequent components optional
builder.optionalStart ( ) .appendPattern ( "HH" ) .appendPattern ( "mm" ) ;
builder.optionalEnd ( ) ; // End of HHmm
// Set default values for missing components to ensure successful parsing
// and to get a consistent result (e.g., start of day/month/year).
// Defaults for YEAR, MONTH, DAY are not strictly needed here since they are in the base pattern.
// However, if the base pattern itself could be optional (e.g., just "yyyy" then "MM" optional),
// these defaults would be critical.
builder.parseDefaulting ( ChronoField.HOUR_OF_DAY , 0 ) ;
builder.parseDefaulting ( ChronoField.MINUTE_OF_HOUR , 0 ) ;
builder.parseDefaulting ( ChronoField.SECOND_OF_MINUTE , 0 ) ;
builder.parseDefaulting ( ChronoField.NANO_OF_SECOND , 0 ) ; // Sets milliseconds to 0
builder.parseDefaulting ( ChronoField.OFFSET_SECONDS , ZoneOffset.UTC .getTotalSeconds ( ) ) ; // Default to UTC offset
DateTimeFormatter formatter = builder
.toFormatter ( )
.withResolverStyle ( ResolverStyle.LENIENT ) ; // Lenient for more forgiving parsing
DateTimeFormatter formatterWithOffset = builder
.toFormatter ( )
.withResolverStyle ( ResolverStyle.LENIENT ) ;
// --- Test cases ---
System .
out .
println ( "Parsing '20230101' (yyyyMMdd): " + formatter.
parseBest ( "20230101" , ZonedDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; System .
out .
println ( "Parsing '20230115' (yyyyMMdd): " + formatter.
parseBest ( "20230115" , ZonedDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; System .
out .
println ( "Parsing '202301151030' (yyyyMMddHHmm): " + formatter.
parseBest ( "202301151030" , ZonedDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; System .
out .
println ( "Parsing '20230115103045' (yyyyMMddHHmmss): " + formatter.
parseBest ( "20230115103045" , ZonedDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; System .
out .
println ( "Parsing '20230115103045123' (yyyyMMddHHmmssSSS): " + formatter.
parseBest ( "20230115103045123" , ZonedDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ;
System .
out .
println ( "Parsing '20230115103045123Z' (yyyyMMddHHmmssSSSZ): " + formatterWithOffset.
parseBest ( "20230115103045123Z" , ZonedDateTime
:: from, OffsetDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; System .
out .
println ( "Parsing '20230115103045123+0500' (yyyyMMddHHmmssSSS+HHMM): " + formatterWithOffset.
parseBest ( "20230115103045123+0500" , ZonedDateTime
:: from, OffsetDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; System .
out .
println ( "Parsing '20230115103045123-08' (yyyyMMddHHmmssSSS-HH): " + formatterWithOffset.
parseBest ( "20230115103045123-08" , ZonedDateTime
:: from, OffsetDateTime
:: from, LocalDateTime
:: from, LocalDate
:: from
) ) ; }
}
}
aW1wb3J0IGphdmEudGltZS5mb3JtYXQuRGF0ZVRpbWVGb3JtYXR0ZXI7CmltcG9ydCBqYXZhLnRpbWUuZm9ybWF0LkRhdGVUaW1lRm9ybWF0dGVyQnVpbGRlcjsKaW1wb3J0IGphdmEudGltZS5mb3JtYXQuUmVzb2x2ZXJTdHlsZTsKaW1wb3J0IGphdmEudGltZS50ZW1wb3JhbC5DaHJvbm9GaWVsZDsKaW1wb3J0IGphdmEudGltZS50ZW1wb3JhbC5UZW1wb3JhbEFjY2Vzc29yOwppbXBvcnQgamF2YS50aW1lLlpvbmVPZmZzZXQ7CmltcG9ydCBqYXZhLnRpbWUuTG9jYWxEYXRlOwppbXBvcnQgamF2YS50aW1lLkxvY2FsRGF0ZVRpbWU7CmltcG9ydCBqYXZhLnRpbWUuWm9uZWREYXRlVGltZTsKaW1wb3J0IGphdmEudGltZS5PZmZzZXREYXRlVGltZTsKCmNsYXNzIElkZW9uZQp7CiAgICBwdWJsaWMgc3RhdGljIHZvaWQgbWFpbihTdHJpbmdbXSBhcmdzKSB7CiAgICAJdHJ5IHsKICAgICAgICAvLyBEZWZpbmUgdGhlIGZvcm1hdHRlciB3aXRoIHllYXIgYXMgdGhlIGZpcnN0IGNvbXBvbmVudCwgZm9sbG93ZWQgYnkgbW9udGggYW5kIGRheQogICAgICAgIERhdGVUaW1lRm9ybWF0dGVyQnVpbGRlciBidWlsZGVyID0gbmV3IERhdGVUaW1lRm9ybWF0dGVyQnVpbGRlcigpCiAgICAgICAgICAgICAgICAuYXBwZW5kUGF0dGVybigieXl5eU1NZGQiKTsgLy8gWWVhciwgTW9udGgsIERheSBhcmUgbm93IHRoZSBiYXNlIG1hbmRhdG9yeSBjb21wb25lbnRzCgogICAgICAgIC8vIE1ha2Ugc3Vic2VxdWVudCBjb21wb25lbnRzIG9wdGlvbmFsCiAgICAgICAgYnVpbGRlci5vcHRpb25hbFN0YXJ0KCkuYXBwZW5kUGF0dGVybigiSEgiKS5hcHBlbmRQYXR0ZXJuKCJtbSIpOwogICAgICAgIGJ1aWxkZXIub3B0aW9uYWxFbmQoKTsgLy8gRW5kIG9mIEhIbW0KCiAgICAgICAgLy8gU2V0IGRlZmF1bHQgdmFsdWVzIGZvciBtaXNzaW5nIGNvbXBvbmVudHMgdG8gZW5zdXJlIHN1Y2Nlc3NmdWwgcGFyc2luZwogICAgICAgIC8vIGFuZCB0byBnZXQgYSBjb25zaXN0ZW50IHJlc3VsdCAoZS5nLiwgc3RhcnQgb2YgZGF5L21vbnRoL3llYXIpLgogICAgICAgIC8vIERlZmF1bHRzIGZvciBZRUFSLCBNT05USCwgREFZIGFyZSBub3Qgc3RyaWN0bHkgbmVlZGVkIGhlcmUgc2luY2UgdGhleSBhcmUgaW4gdGhlIGJhc2UgcGF0dGVybi4KICAgICAgICAvLyBIb3dldmVyLCBpZiB0aGUgYmFzZSBwYXR0ZXJuIGl0c2VsZiBjb3VsZCBiZSBvcHRpb25hbCAoZS5nLiwganVzdCAieXl5eSIgdGhlbiAiTU0iIG9wdGlvbmFsKSwKICAgICAgICAvLyB0aGVzZSBkZWZhdWx0cyB3b3VsZCBiZSBjcml0aWNhbC4KICAgICAgICBidWlsZGVyLnBhcnNlRGVmYXVsdGluZyhDaHJvbm9GaWVsZC5IT1VSX09GX0RBWSwgMCk7CiAgICAgICAgYnVpbGRlci5wYXJzZURlZmF1bHRpbmcoQ2hyb25vRmllbGQuTUlOVVRFX09GX0hPVVIsIDApOwogICAgICAgIGJ1aWxkZXIucGFyc2VEZWZhdWx0aW5nKENocm9ub0ZpZWxkLlNFQ09ORF9PRl9NSU5VVEUsIDApOwogICAgICAgIGJ1aWxkZXIucGFyc2VEZWZhdWx0aW5nKENocm9ub0ZpZWxkLk5BTk9fT0ZfU0VDT05ELCAwKTsgLy8gU2V0cyBtaWxsaXNlY29uZHMgdG8gMAogICAgICAgIGJ1aWxkZXIucGFyc2VEZWZhdWx0aW5nKENocm9ub0ZpZWxkLk9GRlNFVF9TRUNPTkRTLCBab25lT2Zmc2V0LlVUQy5nZXRUb3RhbFNlY29uZHMoKSk7IC8vIERlZmF1bHQgdG8gVVRDIG9mZnNldAoKICAgICAgICBEYXRlVGltZUZvcm1hdHRlciBmb3JtYXR0ZXIgPSBidWlsZGVyCiAgICAgICAgICAgICAgICAudG9Gb3JtYXR0ZXIoKQogICAgICAgICAgICAgICAgLndpdGhSZXNvbHZlclN0eWxlKFJlc29sdmVyU3R5bGUuTEVOSUVOVCk7IC8vIExlbmllbnQgZm9yIG1vcmUgZm9yZ2l2aW5nIHBhcnNpbmcKICAgICAgICAgICAgICAgIAogICAgICAgIERhdGVUaW1lRm9ybWF0dGVyIGZvcm1hdHRlcldpdGhPZmZzZXQgPSBidWlsZGVyCiAgICAgICAgICAgICAgICAudG9Gb3JtYXR0ZXIoKQogICAgICAgICAgICAgICAgLndpdGhSZXNvbHZlclN0eWxlKFJlc29sdmVyU3R5bGUuTEVOSUVOVCk7CgogICAgICAgIC8vIC0tLSBUZXN0IGNhc2VzIC0tLQogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiUGFyc2luZyAnMjAyMzAxMDEnICh5eXl5TU1kZCk6ICIgKyBmb3JtYXR0ZXIucGFyc2VCZXN0KCIyMDIzMDEwMSIsIFpvbmVkRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZTo6ZnJvbSkpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiUGFyc2luZyAnMjAyMzAxMTUnICh5eXl5TU1kZCk6ICIgKyBmb3JtYXR0ZXIucGFyc2VCZXN0KCIyMDIzMDExNSIsIFpvbmVkRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZTo6ZnJvbSkpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiUGFyc2luZyAnMjAyMzAxMTUxMDMwJyAoeXl5eU1NZGRISG1tKTogIiArIGZvcm1hdHRlci5wYXJzZUJlc3QoIjIwMjMwMTE1MTAzMCIsIFpvbmVkRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZTo6ZnJvbSkpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiUGFyc2luZyAnMjAyMzAxMTUxMDMwNDUnICh5eXl5TU1kZEhIbW1zcyk6ICIgKyBmb3JtYXR0ZXIucGFyc2VCZXN0KCIyMDIzMDExNTEwMzA0NSIsIFpvbmVkRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZTo6ZnJvbSkpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiUGFyc2luZyAnMjAyMzAxMTUxMDMwNDUxMjMnICh5eXl5TU1kZEhIbW1zc1NTUyk6ICIgKyBmb3JtYXR0ZXIucGFyc2VCZXN0KCIyMDIzMDExNTEwMzA0NTEyMyIsIFpvbmVkRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZTo6ZnJvbSkpOwoKICAgICAgICBTeXN0ZW0ub3V0LnByaW50bG4oIlBhcnNpbmcgJzIwMjMwMTE1MTAzMDQ1MTIzWicgKHl5eXlNTWRkSEhtbXNzU1NTWik6ICIgKyBmb3JtYXR0ZXJXaXRoT2Zmc2V0LnBhcnNlQmVzdCgiMjAyMzAxMTUxMDMwNDUxMjNaIiwgWm9uZWREYXRlVGltZTo6ZnJvbSwgT2Zmc2V0RGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZVRpbWU6OmZyb20sIExvY2FsRGF0ZTo6ZnJvbSkpOwogICAgICAgIFN5c3RlbS5vdXQucHJpbnRsbigiUGFyc2luZyAnMjAyMzAxMTUxMDMwNDUxMjMrMDUwMCcgKHl5eXlNTWRkSEhtbXNzU1NTK0hITU0pOiAiICsgZm9ybWF0dGVyV2l0aE9mZnNldC5wYXJzZUJlc3QoIjIwMjMwMTE1MTAzMDQ1MTIzKzA1MDAiLCBab25lZERhdGVUaW1lOjpmcm9tLCBPZmZzZXREYXRlVGltZTo6ZnJvbSwgTG9jYWxEYXRlVGltZTo6ZnJvbSwgTG9jYWxEYXRlOjpmcm9tKSk7CiAgICAgICAgU3lzdGVtLm91dC5wcmludGxuKCJQYXJzaW5nICcyMDIzMDExNTEwMzA0NTEyMy0wOCcgKHl5eXlNTWRkSEhtbXNzU1NTLUhIKTogIiArIGZvcm1hdHRlcldpdGhPZmZzZXQucGFyc2VCZXN0KCIyMDIzMDExNTEwMzA0NTEyMy0wOCIsIFpvbmVkRGF0ZVRpbWU6OmZyb20sIE9mZnNldERhdGVUaW1lOjpmcm9tLCBMb2NhbERhdGVUaW1lOjpmcm9tLCBMb2NhbERhdGU6OmZyb20pKTsKICAgIAl9IGNhdGNoIChFeGNlcHRpb24gZSkgewogICAgCQlTeXN0ZW0ub3V0LnByaW50bG4oZSk7CiAgICAJfQogICAgfQp9