2014-04-14 2 views
62

Ich war mit dem neuen Datum Zeit API spielen aber bei der Ausführung dieses:ein Datumsformat das neue Datum Zeit 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); 
    } 
} 

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 auf den Quellcode der Suche von die LOCALDATE Klasse, ich sehe:

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 es in dem Dokument beschrieben:

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

Und alle diese Buchstaben sind defined.

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

Antwort

109

LocalDate repräsentiert nur ein Datum, keine DateTime. "HH: mm: ss" ergibt also keinen Sinn beim Formatieren eines LocalDate. Verwenden Sie stattdessen eine LocalDateTime, vorausgesetzt, Sie möchten sowohl ein Datum als auch eine Uhrzeit darstellen.

25

Ich möchte folgende Details auf die richtige Antwort von @James_D hinzuzufügen:

Hintergrund: meisten Datums- und Zeit-Bibliotheken (java.util.Calendar in Java finden Sie auch .Net-DateTime- oder Date in JavaScript oder DateTime in Perl) basieren auf dem Konzept eines universellen universellen einzigartigen temporalen Typs (auf Deutsch gibt es den poetischen Ausdruck "eierlegende Wollmilchsau"). In diesem Design kann kein nicht unterstütztes Feld sein. Aber der Preis ist hoch: Viele Zeitprobleme können mit einem solchen unflexiblen Ansatz nicht adäquat behandelt werden, da es schwierig ist, einen gemeinsamen Nenner für alle Arten von temporären Objekten zu finden.

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

•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 der UnsupportedTemporalTypeException erklärt. Und wenn wir auf der JSR-310- aussehen mapping of pattern symbols to fields wir sehen, dass das Symbol H zu nicht unterstützten HOUR_OF_DAY abgebildet wird:

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

Dieses Feld Mapping bedeutet nicht, dass das Feld durch den Betontyp unterstützt wird. Das Parsen geschieht in mehreren Schritten. Die Feldzuordnung ist nur der erste Schritt. Der zweite Schritt ist dann das Parsen zu einem Rohobjekt vom Typ TemporalAccessor. Und schließlich parsen Sie Delegaten auf den Zieltyp (hier: LocalDate) und lassen Sie entscheiden, ob sie alle Feldwerte in geparsten Zwischenobjekt akzeptiert.

+0

https://de.wiktionary.org/wiki/eierlegende_Wollmilchsau (wörtlich "Eiablage-Wollmilchsau") Ein All-in-One-Gerät oder eine Person, die nur positive Eigenschaften hat und behauptet welche die Arbeit mehrerer spezialisierter Werkzeuge (oder Versuche) tun können. :-) –

1

LocalDate hat nicht die Zeitinformation, so erhalten Sie eine UnsupportedTemporalTypeException: Unsupported field: HourOfDay.

Sie können LocalDateTime verwenden, aber dann haben Sie nicht die Zeitzone Informationen, also wenn Sie versuchen, auf diese zuzugreifen (auch mit einem der vordefinierten Formatierer) erhalten Sie eine . Die richtige Klasse für mich war ZonedDateTime, die sowohl Zeit als auch Zeitzone enthält

+0

Du hast mir viel Zeit gespart. Danke!!! – Hafiz