Форматирование даты с помощью нового API даты и времени
Я играл с новым API даты и времени, но при запуске этого:
public class Test {
public static void main(String[] args){
String dateFormatted = LocalDate.now()
.format(DateTimeFormatter
.ofPattern("yyyy-MM-dd HH:mm:ss"));
System.out.println(dateFormatted);
}
}
Он бросает:
Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay
at java.time.LocalDate.get0(LocalDate.java:680)
at java.time.LocalDate.getLong(LocalDate.java:659)
at java.time.format.DateTimePrintContext.getValue(DateTimePrintContext.java:298)
at java.time.format.DateTimeFormatterBuilder$NumberPrinterParser.format(DateTimeFormatterBuilder.java:2543)
at java.time.format.DateTimeFormatterBuilder$CompositePrinterParser.format(DateTimeFormatterBuilder.java:2182)
at java.time.format.DateTimeFormatter.formatTo(DateTimeFormatter.java:1745)
at java.time.format.DateTimeFormatter.format(DateTimeFormatter.java:1719)
at java.time.LocalDate.format(LocalDate.java:1685)
at Test.main(Test.java:23)
глядя на исходный код класса LocalDate, я вижу:
private int get0(TemporalField field) {
switch ((ChronoField) field) {
case DAY_OF_WEEK: return getDayOfWeek().getValue();
case ALIGNED_DAY_OF_WEEK_IN_MONTH: return ((day - 1) % 7) + 1;
case ALIGNED_DAY_OF_WEEK_IN_YEAR: return ((getDayOfYear() - 1) % 7) + 1;
case DAY_OF_MONTH: return day;
case DAY_OF_YEAR: return getDayOfYear();
case EPOCH_DAY: throw new UnsupportedTemporalTypeException("Invalid field 'EpochDay' for get() method, use getLong() instead");
case ALIGNED_WEEK_OF_MONTH: return ((day - 1) / 7) + 1;
case ALIGNED_WEEK_OF_YEAR: return ((getDayOfYear() - 1) / 7) + 1;
case MONTH_OF_YEAR: return month;
case PROLEPTIC_MONTH: throw new UnsupportedTemporalTypeException("Invalid field 'ProlepticMonth' for get() method, use getLong() instead");
case YEAR_OF_ERA: return (year >= 1 ? year : 1 - year);
case YEAR: return year;
case ERA: return (year >= 1 ? 1 : 0);
}
throw new UnsupportedTemporalTypeException("Unsupported field: " + field);
}
как это описано в доке:
этот способ будет создать средство форматирования, основанное на простой рисунок буквы и символы, описанные в документации по классу.
и все эти буквы определена.
Почему DateTimeFormatter.ofPattern
не позволяет нам использовать некоторые буквы шаблона?
3 ответа:
LocalDate
представляет только дату, а не время. Поэтому "HH:mm:ss" не имеет смысла при форматировании aLocalDate
. ИспользуйтеLocalDateTime
вместо этого, предполагая, что вы хотите представить как дату, так и время.
Я хотел бы добавить следующие детали к правильному ответу @James_D:
Справочная информация: большинство библиотек даты и времени (
java.util.Calendar
в Java см. Также .Net-DateTime илиDate
в JavaScript илиDateTime
в Perl) основаны на концепции универсального универсального уникального темпорального типа (в немецком языке есть поэтическое выражение "eierlegende Wollmilchsau"). В этой конструкции не может быть неподдерживаемого поля. Но цена высока: многие проблемы не быть адекватно обработанным с таким негибким подходом, потому что трудно невозможно найти общий знаменатель для всех видов временных объектов.JSR-310 выбрал другой путь, а именно разрешить различные временные типы, которые состоят из наборов типов поддерживаемых встроенных полей. Естественным следствием этого является то, что не все возможные поля поддерживаются каждым типом (и пользователи могут даже определять свои собственные специализированные поля). Также возможно программно задать каждый объект типа
TemporalAccessor
для конкретного набора поддерживаемых полей. ИбоLocalDate
мы находим:•DAY_OF_WEEK •ALIGNED_DAY_OF_WEEK_IN_MONTH •ALIGNED_DAY_OF_WEEK_IN_YEAR •DAY_OF_MONTH •DAY_OF_YEAR •EPOCH_DAY •ALIGNED_WEEK_OF_MONTH •ALIGNED_WEEK_OF_YEAR •MONTH_OF_YEAR •PROLEPTIC_MONTH •YEAR_OF_ERA •YEAR •ERA
там нет HOUR_OF_DAY-поле, которое объясняет проблему
UnsupportedTemporalTypeException
. А если посмотреть на JSR-310 -отображение символов шаблона в поля мы видим, что символ H отображается на неподдерживаемый HOUR_OF_DAY:/** Map of letters to fields. */ private static final Map<Character, TemporalField> FIELD_MAP = new HashMap<>(); static { FIELD_MAP.put('G', ChronoField.ERA); FIELD_MAP.put('y', ChronoField.YEAR_OF_ERA); FIELD_MAP.put('u', ChronoField.YEAR); FIELD_MAP.put('Q', IsoFields.QUARTER_OF_YEAR); FIELD_MAP.put('q', IsoFields.QUARTER_OF_YEAR); FIELD_MAP.put('M', ChronoField.MONTH_OF_YEAR); FIELD_MAP.put('L', ChronoField.MONTH_OF_YEAR); FIELD_MAP.put('D', ChronoField.DAY_OF_YEAR); FIELD_MAP.put('d', ChronoField.DAY_OF_MONTH); FIELD_MAP.put('F', ChronoField.ALIGNED_DAY_OF_WEEK_IN_MONTH); FIELD_MAP.put('E', ChronoField.DAY_OF_WEEK); FIELD_MAP.put('c', ChronoField.DAY_OF_WEEK); FIELD_MAP.put('e', ChronoField.DAY_OF_WEEK); FIELD_MAP.put('a', ChronoField.AMPM_OF_DAY); FIELD_MAP.put('H', ChronoField.HOUR_OF_DAY); FIELD_MAP.put('k', ChronoField.CLOCK_HOUR_OF_DAY); FIELD_MAP.put('K', ChronoField.HOUR_OF_AMPM); FIELD_MAP.put('h', ChronoField.CLOCK_HOUR_OF_AMPM); FIELD_MAP.put('m', ChronoField.MINUTE_OF_HOUR); FIELD_MAP.put('s', ChronoField.SECOND_OF_MINUTE); FIELD_MAP.put('S', ChronoField.NANO_OF_SECOND); FIELD_MAP.put('A', ChronoField.MILLI_OF_DAY); FIELD_MAP.put('n', ChronoField.NANO_OF_SECOND); FIELD_MAP.put('N', ChronoField.NANO_OF_DAY); }
это сопоставление полей не означает, что поле поддерживается конкретным типом. Разбор происходит в несколько этапов. Сопоставление полей - это только первый шаг. Второй шаг-это разбор на необработанный объект типа
TemporalAccessor
. И, наконец, разбор делегатов на целевой тип (здесь:LocalDate
) и пусть он решает, принимает ли он все значения полей в разбираемом промежуточном объекте.
LocalDate
не имеет информации о времени, так что вы получитеUnsupportedTemporalTypeException: Unsupported field: HourOfDay
.можно использовать
LocalDateTime
но тогда у вас нет информации о часовом поясе, поэтому, если вы попытаетесь получить доступ к этому (даже с помощью одного из предопределенных форматеров), вы получитеUnsupportedTemporalTypeException: Unsupported field: OffsetSeconds
.правильный класс для меня был
ZonedDateTime
, который включает в себя как время и часовой пояс.