L’analisi di una stringa in formato data in date java predefinite su 1 e mese a gennaio

Sto cercando di accettare un input di data utente nel formato come “2000 hrs, Thursday, July 20, 2015”. Quindi convertirò questo in un formato data per eseguire operazioni su di esso. Ma la conversione da stringa ad oggi è il mese predefinito a gennaio e la data a 1. Ecco lo snippet di codice:

String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, YYYY"; SimpleDateFormat userDateFormatter = new SimpleDateFormat(userDateFormat); String reference_date = "2000 hrs, Thursday, July 20, 2015"; Date date = null; try { date = userDateFormatter.parse(reference_date); } catch (ParseException e) { System.out.println("Date must be in the format " + userDateFormat); } System.out.println(userDateFormatter.format(date)); 

Il seguente metodo blocca le stampe: 2000 ore, giovedì 1 gennaio 2015. Qualche indizio perché?

Perché hai usato YYYY quando avevi bisogno di yyyy e il 20 luglio 2015 era un lunedì. Volevi qualcosa del genere

 String userDateFormat = "HHmm 'hrs', EEEE, MMMM dd, yyyy"; SimpleDateFormat userDateFormatter = new SimpleDateFormat( userDateFormat); String reference_date = "2000 hrs, Monday, July 20, 2015"; 

che poi emette

 2000 hrs, Monday, July 20, 2015 

Quindi SimpleDateFormat Javadoc dice (in parte)

 Letter Date or Time Component Presentation Examples G Era designator Text AD y Year Year 1996; 96 Y Week year Year 2009; 09 

java.time

  DateTimeFormatter userDateTimeFormatter = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH); String referenceDate = "2000 hrs, Monday, July 20, 2015"; LocalDateTime dateTime = LocalDateTime.parse(referenceDate, userDateTimeFormatter); System.out.println(dateTime.format(userDateTimeFormatter)); 

L’output è:

2000 ore, lunedì 20 luglio 2015

La risposta di Elliott Frisch è corretta. Contribuisco alla risposta moderna utilizzando java.time , la moderna API di data e ora Java. Quando è stata posta questa domanda, era fuori da un anno e mezzo. Adesso ha quattro anni e è molto diffuso. Sto inoltre dando un locale esplicito. L’ora della data è in inglese e, anche se probabilmente lo sono anche le impostazioni locali predefinite, il codice che si basa su quello si interromperà se un giorno lo si esegue su un computer in una diversa localizzazione o semplicemente si modifica la propria impostazione locale.

Sei lontano dall’unico errore nell’usare un caso errato in una stringa di pattern format. Domande su questo argomento vengono sempre poste su Stack Overflow. SimpleDateFormat è rinomato per la sua recitazione: ti dà un risultato errato e fa finta che tutto SimpleDateFormat bene, dove ti saresti aspettato che notificasse che qualcosa non andava, per esempio lanciando un’eccezione.

La moderna API genera un’eccezione quando gli dai input errati che può rilevare. Per esempio:

  DateTimeFormatter userDateTimeFormatter = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, YYYY", Locale.ENGLISH); String referenceDate = "2000 hrs, Thursday, July 20, 2015"; 

Risultato:

java.time.DateTimeException: imansible ottenere LocalDate da TemporalAccessor: {MonthOfYear = 7, DayOfWeek = 4, WeekBasedYear [WeekFields [SUNDAY, 1]] = 2015, DayOfMonth = 20}, ISO risolto a 20:00 di tipo java.time .format.Parsed

Non è molto leggibile. La cosa da notare è “WeekBasedYear”. Un anno basato sulla settimana è utile solo con un numero di settimana, quindi è sbagliato qui. E i documenti ti diranno che era YYYY maiuscolo che ti ha dato questo. Risolviamo:

  DateTimeFormatter userDateTimeFormatter = DateTimeFormatter.ofPattern("HHmm 'hrs', EEEE, MMMM dd, uuuu", Locale.ENGLISH); 

Con DateTimeFormatter è consuetudine utilizzare uuuu per l’anno. yyyy funziona anche per anni dopo l’anno 0. Tuttavia, non abbiamo ancora finito:

java.time.DateTimeException: Conflitto trovato: Field DayOfWeek 1 si differenzia da DayOfWeek 4 derivato dal 2015-07-20

La moderna API rifiuta anche di accettare un giorno della settimana errato, in modo da ottenere la convalida completa della data (c’è un trucco per persuaderla, però, se non vuoi questa convalida). Come ha già detto Elliott Frisch, il 20 luglio 2015 era un lunedì (giorno 1 della settimana), non un giovedì. Nel mio primo frammento sopra ho anche corretto questo errore, quindi funziona.

Link: tutorial Oracle: Data Ora che spiega come utilizzare java.time .