Prelevare una data da un form html con Spring Boot / Thymeleaf

di il
4 risposte

Prelevare una data da un form html con Spring Boot / Thymeleaf

Devo prelevare una data presa da un form con Spring Boot e ho risolto in questo modo (la mia classe funziona perfettamente):
Pagina html:

	<td><input id="data" type="datetime-local" th:field="*{data}"/></td>
Variabile che riceve dalla pagina html il valore:

	@DateTimeFormat(pattern = "yyyy-MM-dd'T'HH:mm")
	private LocalDateTime data;
Ma non sono convinto di aver preso tutte le cautele del caso.
Mi sembra di aver capito questo:
1) Il browser prende il formato di LocalDateTime dal sistema operativo (in Italia "gg/mm/aaaa --:--");
2) Spring Boot imposta il formato "yyyy-MM-dd'T'HH:mm" per memorizzare la data scritta dall'utente nel browser dentro l'oggetto di tipo LocalDateTime.
DOMANDE:
A) Spring Boot riceve dal browser la formattazione della stringa inserita dall'utente ("gg/mm/aaaa HH:mm") e quindi se il browser dovesse obbligare l'utente ad una formattazione diversa Spring Boot sarebbe informato oppure no?
B) "yyyy-MM-dd'T'HH:mm" è il formato standard di lettura di una stringa da parte di un oggetto Java di tipo LocalDateTime?

4 Risposte

  • Re: Prelevare una data da un form html con Spring Boot / Thymeleaf

    iBaffiPro ha scritto:


    1) Il browser prende il formato di LocalDateTime dal sistema operativo (in Italia "gg/mm/aaaa --:--");
    2) Spring Boot imposta il formato "yyyy-MM-dd'T'HH:mm" per memorizzare la data scritta dall'utente nel browser dentro l'oggetto di tipo LocalDateTime.
    Il tipo di input datetime-local è ben documentato. Basta anche solo vedere sul solito MDN di Mozilla:
    https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local

    La documentazione dice una cosa molto chiara: la visualizzazione/input della data segue la localizzazione dell'utente come indicato dal SO, quindi su una macchina "italiana" vedi gg/mm/aaaa, --:-- mentre su un'altra macchina con diversa localizzazione vedi differente.
    Ma questo non importa, perché il value interno che è quello inviato al submit è SEMPRE nel formato YYYY-MM-DDThh:mm che per intenderci, questo è il formato standard ISO per i date/time "local".

    Ci sono però diversi problemi, anche questi sono documentati.

    1) L'input essendo di una data "locale", permette di inserire una data/ora che "esiste" in un Locale (ad esempio quello dell'utente) ma che "non esiste" in un altro Locale. Su questo purtroppo c'è da ragionare e valutare cosa fare in base a come ti aspetti di usare questa data/ora.

    2) Esiste un altro problema ancora peggiore: la "degradazione" del campo. Sui browser che supportano questo nuovo tipo di campo, quanto detto sopra è valido e al submit invia sempre nel formato YYYY-MM-DDThh:mm. Ma se il tipo di campo non è supportato, viene "degradato" ad un semplice ed equivalente input type="text" e qui l'utente può inserire quello che gli pare e NON c'è alcun controllo/normalizzazione del valore al submit.

    iBaffiPro ha scritto:


    A) Spring Boot riceve dal browser la formattazione della stringa inserita dall'utente ("gg/mm/aaaa HH:mm") e quindi se il browser dovesse obbligare l'utente ad una formattazione diversa Spring Boot sarebbe informato oppure no?
    B) "yyyy-MM-dd'T'HH:mm" è il formato standard di lettura di una stringa da parte di un oggetto Java di tipo LocalDateTime?
    A) nel caso di degradazione del campo, ovviamente NON puoi sapere a priori cosa ti invia l'utente.
    B) YYYY-MM-DDThh:mm è solamente lo standard ISO. Ma puoi parsare/formattare le date/ore in tanti altri formati.
  • Re: Prelevare una data da un form html con Spring Boot / Thymeleaf

    Scusa per il ritardo ma ho avuto un po’ di impegni e mi sono distratto da questo quesito. Grazie per la tua celere risposta e complimenti per la tua formidabile preparazione.
    1) L'input essendo di una data "locale", permette di inserire una data/ora che "esiste" in un Locale (ad esempio quello dell'utente) ma che "non esiste" in un altro Locale. Su questo purtroppo c'è da ragionare e valutare cosa fare in base a come ti aspetti di usare questa data/ora.
    Non comprendo bene questo punto. Quando inserisco una data mi accontento che sia successiva alla data di oggi. Per capirci pensa alla data che un comune CMS come WordPress mette ad una nuova news inserita da un utente. Se ti riferisci al fatto che l’ora attuale in Italia, a Tokyo, appartenga già al passato non è un problema.
    2) Esiste un altro problema ancora peggiore: la "degradazione" del campo. Sui browser che supportano questo nuovo tipo di campo, quanto detto sopra è valido e al submit invia sempre nel formato YYYY-MM-DDThh:mm. Ma se il tipo di campo non è supportato, viene "degradato" ad un semplice ed equivalente input type="text" e qui l'utente può inserire quello che gli pare e NON c'è alcun controllo/normalizzazione del valore al submit.
    Questo problema l’ho sto sperimentando su IE, sugli altri browser fortunatamente no ma editando l’html sui browser più evoluti posso incorrere nello stesso inconveniente. Quando al posto della data scrivo una stringa a caso, Spring Boot rimanda l’utente alla pagina di errore sconosciuto. Stesso discorso per quando scrivo “ciao” in un tag che dovrebbe restituire un numero. Come gestisco un campo diverso dal normale testo? È scomodo dover impostare tutto come una stringa? Tu con Spring Boot gestisci tutto come una stringa?
  • Re: Prelevare una data da un form html con Spring Boot / Thymeleaf

    iBaffiPro ha scritto:


    Non comprendo bene questo punto. Quando inserisco una data mi accontento che sia successiva alla data di oggi. Per capirci pensa alla data che un comune CMS come WordPress mette ad una nuova news inserita da un utente. Se ti riferisci al fatto che l’ora attuale in Italia, a Tokyo, appartenga già al passato non è un problema.
    Il problema di avere "solo" una data nel formato gg/mm/aaaa hh:mm (con o senza secondi/millisecondi) SENZA avere altre informazioni di contesto, riguarda più che altro una serie di casi particolari tra cui ad esempio il passaggio dall'ora solare a legale.

    In Italia l'ora legale inizia l'ultima domenica di Marzo. Che quest'anno vuol dire il giorno 28 Marzo 2021. In quella data si è passati dalle 01:59:59 direttamente alle 03:00:00.
    Quindi ad esempio la data/orario "28/03/2021 02:24" in Italia "non esiste". E lo si può provare da codice:
    DateFormat df = new SimpleDateFormat("dd/MM/yyyy HH:mm");
    df.setTimeZone(TimeZone.getTimeZone("Europe/Rome"));
    df.setLenient(false);
    
    Date d = df.parse("28/03/2021 02:24");
    System.out.println(df.format(d));
    Se provi ad eseguire questo, ti becchi java.text.ParseException: Unparseable date: "28/03/2021 02:24"
    Non è un problema di formato/sintassi ... è proprio che quell'orario NON ESISTE!
    Nota che il DateFormat ha il lenient=false, ovvero NON è "indulgente". Se lo imposti true, ti accetta la data e la considera "03:24".

    Se invece metti un altro fuso orario es. "America/New_York", allora non lancia ParseException, semplicemente perché in QUEL fuso orario questa data/orario locale "esiste".

    Tutto questo per dire una cosa molto semplice: se hai solo una data/orario tipo "28/03/2021 02:24" e NON hai altre informazioni di contesto (fuso orario), non puoi davvero sapere se questa data/orario esiste ed è valida.
    Quindi dipende appunto da cosa te ne fai solo di una data del genere se non ci associ "altro" di contesto. Se la salvi e la fai rivedere a quello stesso utente, ok, l'utente "sa" che quella data che ha inserito è nel suo fuso orario. Ma non la puoi usare per farci logiche o confronti con altre date-orari.

    iBaffiPro ha scritto:


    Questo problema l’ho sto sperimentando su IE, sugli altri browser fortunatamente no ma editando l’html sui browser più evoluti posso incorrere nello stesso inconveniente. Quando al posto della data scrivo una stringa a caso, Spring Boot rimanda l’utente alla pagina di errore sconosciuto. Stesso discorso per quando scrivo “ciao” in un tag che dovrebbe restituire un numero. Come gestisco un campo diverso dal normale testo? È scomodo dover impostare tutto come una stringa? Tu con Spring Boot gestisci tutto come una stringa?
    Una possibilità sarebbe usare nelle tue pagine la libreria Modernizr (https://modernizr.co) che fornisce informazioni sul supporto di molte feature di browser/HTML. Se il type="datetime-local" non è supportato, potresti fornire un messaggio all'utente o fare altre logiche per "sistemare" il formato prima del submit.
  • Re: Prelevare una data da un form html con Spring Boot / Thymeleaf

    Risposta impeccabile! Grazie mille!

    Mi studierò questa libreria che non conosco. Al momento non riesco neppure a scaricare il sorgente dal sito...

    Comunque avrei preferito inserire un controllo anche da Spring Boot ed evitare che l'applicazioni si schianti? Per caso sai se c'è qualche tecnica, annotazione, ecc... che posso aggiungere oltre a modernizr?
Devi accedere o registrarti per scrivere nel forum
4 risposte