Formatieren Sie ein Datum mit der neuen Datumszeit-API

Lesezeit: 2 Minuten

Benutzer-Avatar
Benutzer2336315

Ich habe mit der neuen Datumszeit-API gespielt, aber beim Ausführen:

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);
    }
}

Es wirft:

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)

Wenn ich mir den Quellcode der LocalDate-Klasse ansehe, sehe ich:

  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);
    }

Wie im Dokument beschrieben:

Diese Methode erstellt einen Formatierer, der auf einem einfachen Muster aus Buchstaben und Symbolen basiert, wie in der Klassendokumentation beschrieben.

Und all diese Buchstaben sind definiert.

Warum also DateTimeFormatter.ofPattern erlaubt uns nicht, einige Musterbuchstaben zu verwenden?

LocalDate stellt nur ein Datum dar, keine DateTime. Also macht “HH:mm:ss” beim Formatieren von a keinen Sinn LocalDate. Verwenden ein LocalDateTime Angenommen, Sie möchten sowohl ein Datum als auch eine Uhrzeit darstellen.

  • Wie kann ich diese Antwort positiv bewerten und die Tatsache negativ bewerten, dass es sowohl ein LocalDate- als auch ein LocalDateTime-Objekt gibt …

    – Xials

    4. Oktober 2019 um 21:47 Uhr

  • Ich würde gerne nur mit LocalTime arbeiten, wie führen Sie die Formatierung durch, ohne auf diese Ausnahme zu stoßen java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: DayOfWeek

    – Samuel Owino

    11. Januar 2020 um 23:11 Uhr


  • Macht nichts: Das funktioniert DateTimeFormatter.ofPattern("HH:mm:ss")

    – Samuel Owino

    11. Januar 2020 um 23:22 Uhr

  • @samuelowino Bei mir hat das funktioniert: DateTimeFormatter.ofPattern("HH:mm").withZone(ZoneId.systemDefault()).format(...). <-- Hinzufügen der .withZone(…).

    – Jan

    12. Oktober 2020 um 16:15 Uhr


  • Ich habe benutzt DateTime dateTime = DateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(defaultLocale).withZone(defaultTimeZone.toZoneId()); Das bekommt mich Exception in thread "main" java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds Als @isapir unten rechts: ZonedDateTime. Dann funktioniert es auch dafür. Also landete ich bei ZonedDateTime dateTime = ZonedDateTime.now(); DateTimeFormatter formatter = DateTimeFormatter.RFC_1123_DATE_TIME.withLocale(defaultLocale).withZone(defaultTimeZone.toZoneId());

    – Benutzer637338

    17. Dezember 2021 um 23:49 Uhr


Ich möchte der richtigen Antwort von @James_D folgende Details hinzufügen:

Hintergrund: Die meisten Datums-und-Uhrzeit-Bibliotheken (java.util.Calendar in Java siehe auch .Net-DateTime bzw Date in JavaScript bzw DateTime in Perl) basieren auf dem Konzept eines universellen, universellen, einmaligen zeitlichen Typs (im Deutschen gibt es den poetischen Ausdruck “eierlegende Wollmilchsau”). In diesem Design kann es kein nicht unterstütztes Feld geben. Aber der Preis ist hoch: Viele Zeitprobleme lassen sich mit einem so unflexiblen Ansatz nicht angemessen handhaben, weil es schwierig bis unmöglich ist, einen gemeinsamen Nenner für alle Arten von zeitlichen Objekten zu finden.

JSR-310 hat einen anderen Weg gewählt, nämlich verschiedene zeitliche Typen zuzulassen, die aus typspezifischen Sätzen von unterstützten eingebauten Feldern bestehen. Die natürliche Konsequenz ist, dass nicht jedes mögliche Feld von jedem Typ unterstützt wird (und Benutzer können sogar ihre eigenen spezialisierten Felder definieren). Es ist auch möglich programmgesteuert fragen jedes Objekt des Typs TemporalAccessor für seinen spezifischen Satz von unterstützten Feldern. Zum LocalDate wir finden:

•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 

Es gibt kein HOUR_OF_DAY-Feld, das das Problem erklärt UnsupportedTemporalTypeException. Und wenn wir uns den JSR-310-Zuordnung von Mustersymbolen zu Feldern Wir sehen, dass das Symbol H dem nicht unterstützten HOUR_OF_DAY zugeordnet ist:

/** 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);    
}

Diese Feldzuordnung bedeutet nicht, dass das Feld vom konkreten Typ unterstützt wird. Das Parsing erfolgt in mehreren Schritten. Die Feldzuordnung ist nur der erste Schritt. Der zweite Schritt ist dann das Parsen zu einem rohen Objekt des Typs TemporalAccessor. Und schließlich Parsing-Delegates zum Zieltyp (hier: LocalDate) und lassen Sie es entscheiden, ob es alle Feldwerte im geparsten Zwischenobjekt akzeptiert.

  • en.wiktionary.org/wiki/eierlegende_Wollmilchsau (wörtlich „eierlegende Wollmilchsau“) Ein All-in-One-Gerät oder eine Person, die nur positive Eigenschaften hat (oder zu haben behauptet) und die die Arbeit mehrerer spezialisierter Werkzeuge erledigen kann (oder versucht). 🙂

    – Trevor Robinson

    11. Mai 2017 um 20:32 Uhr

Benutzer-Avatar
isapir

Der richtige Kurs für mich war ZonedDateTime die sowohl Zeit als auch Zeitzone umfasst.

LocalDate hat nicht die Zeitinformationen, also erhalten Sie a UnsupportedTemporalTypeException: Unsupported field: HourOfDay.

Sie können verwenden LocalDateTime aber dann haben Sie die Zeitzoneninformationen nicht. Wenn Sie also versuchen, darauf zuzugreifen (selbst mit einem der vordefinierten Formatierer), erhalten Sie eine UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds.

  • Diese Antwort sollte die akzeptierte Antwort sein oder zur aktuellen akzeptierten Antwort hinzugefügt werden.

    – Gourabix

    1. Februar um 14:10 Uhr

  • Inconvertible types; cannot cast 'java.time.LocalDateTime' to 'java.time.ZonedDateTime' :/

    – MarkHu

    26. Februar um 0:53


Ich hatte ein ähnliches Problem mit diesem Code:

DateTimeFormatter.RFC_1123_DATE_TIME.format(new Date().toInstant())

java.time.temporal.UnsupportedTemporalTypeException: Nicht unterstütztes Feld: DayOfMonth

Ich habe es so gelöst:

DateTimeFormatter.RFC_1123_DATE_TIME.format(
    ZonedDateTime.ofInstant(new Date().toInstant(), ZoneId.systemDefault()))

1344810cookie-checkFormatieren Sie ein Datum mit der neuen Datumszeit-API

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy