Problems migrating from SimpleDateFormat to DateTimeFormatter

I have successfully used the SimpleDateFormatlast couple of years. I built a bunch of utility classes using it.

As I ran into SimpleDateFormatnon-thread safe (SDF) issues , I spent the last couple of days reorganizing these utility classes to use DateTimeFormatter(DTF) now. Since the timing diagrams of both classes are almost identical, this transition seemed like a good idea at the time.

Now I am having problems getting EpochMillis(milliseconds s 1970-01-01T00:00:00Z): while the SDF will be, for example. interpreted 10:30parsed using HH:mmboth 1970-01-01T10:30:00Z, DTF does not do the same. DTF can use 10:30for analysis a LocalTime, but not ZonedDateTime, which is necessary to obtain EpochMillis.

I understand that objects java.timefollow a different philosophy; Date, Timeand Zonedobjects are stored separately. However, in order for my utility class to interpret all the lines as it was before, I need to be able to define the default parsing for all missing objects dynamically. I tried to use

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseDefaulting(ChronoField.YEAR, 1970);
builder.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1);
builder.parseDefaulting(ChronoField.DAY_OF_MONTH, 1);
builder.parseDefaulting(ChronoField.HOUR_OF_DAY, 0);
builder.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0);
builder.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
builder.append(DateTimeFormatter.ofPattern(pattern));

. , , pattern. , ChronoField pattern, ?

TemporalAccessor temporal = formatter.parseBest(time,
        ZonedDateTime::from,
        LocalDateTime::from,
        LocalDate::from,
        LocalTime::from,
        YearMonth::from,
        Year::from,
        Month::from);
if ( temporal instanceof ZonedDateTime )
    return (ZonedDateTime)temporal;
if ( temporal instanceof LocalDateTime )
    return ((LocalDateTime)temporal).atZone(formatter.getZone());
if ( temporal instanceof LocalDate )
    return ((LocalDate)temporal).atStartOfDay().atZone(formatter.getZone());
if ( temporal instanceof LocalTime )
    return ((LocalTime)temporal).atDate(LocalDate.of(1970, 1, 1)).atZone(formatter.getZone());
if ( temporal instanceof YearMonth )
    return ((YearMonth)temporal).atDay(1).atStartOfDay().atZone(formatter.getZone());
if ( temporal instanceof Year )
    return ((Year)temporal).atMonth(1).atDay(1).atStartOfDay().atZone(formatter.getZone());
if ( temporal instanceof Month )
    return Year.of(1970).atMonth((Month)temporal).atDay(1).atStartOfDay().atZone(formatter.getZone());

.

//-/ -?

+4
2

Java-8-:

, .

, (, , ):

private static final DateTimeFormatter FLEXIBLE_FORMATTER;

static {
    DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
    builder.appendPattern("MM/dd");
    builder.parseDefaulting(ChronoField.YEAR_OF_ERA, 1970);
    builder.parseDefaulting(ChronoField.MONTH_OF_YEAR, 1);
    builder.parseDefaulting(ChronoField.DAY_OF_MONTH, 1);
    builder.parseDefaulting(ChronoField.HOUR_OF_DAY, 0);
    builder.parseDefaulting(ChronoField.MINUTE_OF_HOUR, 0);
    builder.parseDefaulting(ChronoField.SECOND_OF_MINUTE, 0);
    FLEXIBLE_FORMATTER = builder.toFormatter();
}

:

parseDefaulting(...) , . , , . (: MONTH_OF_YEAR "MM/dd" "07/13" ), . , , ( 7, 1).

API :

. , , . , . , .

:

parseDefaulting(...) .

1:

, parseBest(...), ,

  • (MonthDay?) .. .

  • .

2:

, . , , Time4J, , , . Time4J " //-/ -?" MultiFormatParser.

UPDATE:

Java-8: ChronoField.YEAR_OF_ERA ChronoField.YEAR, "y" (= -, , gregorian year). . . , .

+3

java.time, , . , , , Joda . . , , , String Date. . : Java 8 java.time:

0

Source: https://habr.com/ru/post/1660552/


All Articles