2014-04-14 16 views
62

stavo giocando con la nuova API data e ora, ma quando si esegue questo:Formattare una data utilizzando la nuova API di data e ora

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

Getta:

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) 

Se si guarda il codice sorgente di la classe LocalDate, vedo:

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

Come descritto nel documento:

Questo metodo creerà un formattatore basato su un modello semplice di lettere e simboli come descritto nella documentazione della classe.

E tutte queste lettere sono defined.

Quindi, perché DateTimeFormatter.ofPattern non ci consente di utilizzare alcune lettere di pattern?

risposta

109

LocalDate rappresenta solo una data, non un DateTime. Quindi "HH: mm: ss" non ha senso quando si formatta uno LocalDate. Utilizzare invece LocalDateTime, assumendo che si desideri rappresentare sia una data che un'ora.

25

vorrei aggiungere seguenti dettagli per la risposta corretta di @James_D:

Background: La maggior parte dei data-e-Time-librerie (java.util.Calendar in Java, puoi anche .Net-datetime o Date in JavaScript o DateTime in Perl) si basano sul concetto di un tipo temporale universale universale per tutti gli usi (in tedesco esiste l'espressione poetica "eierlegende Wollmilchsau"). In questo progetto non ci può essere un campo non supportato. Ma il prezzo è alto: molti problemi temporali non possono essere adeguatamente gestiti con un approccio così flessibile perché è difficile trovare un denominatore comune per tutti i tipi di oggetti temporali.

JSR-310 ha scelto un altro modo, vale a dire consentire tipi temporali diversi che consistono in insiemi di tipi specifici di campi integrati supportati. La conseguenza naturale è che non tutti i campi possibili sono supportati da ogni tipo (e gli utenti possono persino definire i loro campi specializzati). È inoltre possibile programmatically ask ogni oggetto di tipo TemporalAccessor per il suo insieme specifico di campi supportati. Per LocalDate troviamo:

•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 

Non c'è HOUR_OF_DAY-campo che spiega il problema della UnsupportedTemporalTypeException. E se guardiamo la JSR-310- mapping of pattern symbols to fields vediamo che il simbolo H viene mappato HOUR_OF_DAY non supportato:

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

mappatura Questo campo non significa che il campo è supportata dal tipo concreto. L'analisi avviene in diversi passaggi. La mappatura dei campi è solo il primo passo. Il secondo passaggio è quindi l'analisi di un oggetto non elaborato di tipo TemporalAccessor. Infine, analizza i delegati al tipo di destinazione (qui: LocalDate) e lascia decidere se accetta tutti i valori dei campi nell'oggetto intermedio analizzato.

+0

https://en.wiktionary.org/wiki/eierlegende_Wollmilchsau (letteralmente "uovo-deposizione di lana-latte-scrofa") Un dispositivo o una persona all-in-one che ha (o afferma di avere) solo attributi positivi e che può (o tenta di) fare il lavoro di diversi strumenti specializzati. :-) –

1

LocalDate non ha le informazioni sull'ora in modo da ottenere un UnsupportedTemporalTypeException: Unsupported field: HourOfDay.

È possibile utilizzare LocalDateTime ma non si dispone delle informazioni sul fuso orario, quindi se si tenta di accedervi (anche utilizzando uno dei formattatori predefiniti) verrà visualizzato il numero UnsupportedTemporalTypeException: Unsupported field: OffsetSeconds.

La classe giusta per me era ZonedDateTime che include sia Ora che Fuso orario.

+0

Mi hai salvato un sacco di tempo. grazie!!! – Hafiz