Я успешно использовал SimpleDateFormat
последние пару лет. Используя это, я создал кучу классов полезности.Проблемы при переходе с SimpleDateFormat на DateTimeFormatter
Как я столкнулся с проблемами, когда SimpleDateFormat
(SDF) не был потокобезопасным, я потратил последние пару дней на реорганизацию этих служебных классов, чтобы внутренне использовать DateTimeFormatter
(DTF). Поскольку временные диаграммы обоих классов почти идентичны, этот переход казался хорошей идеей в то время.
У меня возникли проблемы с получением EpochMillis
(миллисекунды с 1970-01-01T00:00:00Z
): хотя SDF будет, например, интерпретировать 10:30
с использованием HH:mm
как 1970-01-01T10:30:00Z
, DTF не делает то же самое. DTF может использовать 10:30
для разбора LocalTime
, но не ZonedDateTime
, который необходим для получения EpochMillis
.
Я понимаю, что объекты java.time
следуют другой философии; Date
, Time
и Zoned
объекты хранятся отдельно. Однако для того, чтобы мой класс утилиты интерпретировал все строки, как это было раньше, мне нужно иметь возможность определять синтаксический анализ по умолчанию для всех отсутствующих объектов динамически. Я попытался использовать
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
s определены в 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());
, которая не покрывает все случаи либо.
Какова наилучшая стратегия для динамического анализа даты/времени/даты-времени/зоны-даты-времени?
Если проблема была просто защитой от потоков, почему решение не защищало доступ к формату с помощью 'synchronized' блоков? – BadZen
Да, оригинальная проблема была действительно просто потокобезопасной; но теперь я потратил немало времени и сил на то, чтобы переместить вещи, и я бы просто хотел, чтобы это работало ... Я не могу поверить, что установка общих параметров разбора по умолчанию невозможна в 'java.time'. – dotwin
Похоже на ошибочное падение стоимости на данный момент, честно ... Конечно, вы можете применить зону к своему местному времени, а затем измерить миллионы с эпохи: 'ZonedDateTime zdt = local.atZone (ZoneId.of (« Америка/New_York "));' Но похоже, что вы добавляете сложность без причины. – BadZen