2011-09-30 6 views
43

Qui lenient viene utilizzato in Java DateFormat. Ho controllato il documento, ma non ho capito cosa stava dicendo.Qual è l'uso di "lenient"?

Qualcuno può dirmi qual è l'uso di questo lenient, con un esempio in tempo reale in cui viene utilizzato?

+1

FYI, 'DateFormat' è una delle classi fastidiosi scendere Data in tempo che ora sono l'eredità, soppiantato dalle classi java.time. Utilizzare ['java.time.format.DateTimeFormatter'] (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html). –

risposta

4

È possibile impostare l'analizzatore di date come non troppo utile se si desidera che accetti rigorosamente un formato di data fornito. E 'ben spiegata in the doc:

Per default, l'analisi è clementi: Se l'ingresso non è nella forma usata dal metodo format di questo oggetto, ma può ancora essere analizzato come una data, quindi parse riesce. I clienti possono insistere sulla stretta osservanza del formato chiamando lo setLenient(false).

20

Per esempio, questo:

SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy"); 
System.out.println(simpleDateFormat.parse("0")); 
simpleDateFormat.setLenient(false); 
System.out.println(simpleDateFormat.parse("0")); 

risultati in:

Thu Jan 01 00:00:00 CET 1 
Exception in thread "main" java.text.ParseException: Unparseable date: "0" 
    at java.text.DateFormat.parse(Unknown Source) 
    at net.java.quickcheck.generator.support.X.main(X.java:28) 
+2

Perché il codice seguente sta funzionando. ? SimpleDateFormat simpleDateFormat = new SimpleDateFormat ("yyyy"); \t \t \t System.out.println (simpleDateFormat.parse ("4")); \t \t \t simpleDateFormat.setLenient (false); \t \t \t System.out.println (simpleDateFormat.parse ("4")); – KSHiTiJ

+0

Causa lì (nel calendario gregoriano che è l'impostazione predefinita di Java) non è un anno "0". Dopo 1 BC (che si tradurrebbe in -1 AFAIK) segue 1 AD (che è, beh, 1). Quindi "0" sopra è (leniently) trattato come "0 anni (dopo il primo anno, che è 1)" e risulta in 1. Se l'analisi lenta è disabilitata, viene lanciata l'eccezione. In altre parole, non si controlla l'input di 4 cifre ben formattato con quel codice. (Anche 300 AD, "300" sarebbe un anno aaaa valido, ovviamente) – chammp

40

Il javadoc afferma chiaramente:

Specificare se la data/ora di analisi è quello di essere indulgenti . Con l'analisi lenta di , il parser può utilizzare l'analisi euristica per interpretare gli input che non corrispondono esattamente al formato di questo oggetto. Con l'analisi rigorosa, gli input devono corrispondere al formato di questo oggetto.

Quindi, se si dispone di un modello e creare un oggetto Date che rigorosamente partite il vostro modello, impostare indulgente a false. Inoltre, DateFormat è indulgente, per impostazione predefinita.

In sostanza, DateFormat set Calendar.setLenient e gli stati Javadoc:

di specificare se l'interpretazione data/ora è di essere indulgente. Con un'interpretazione indulgente, una data come "Febbraio 942, 1996" sarà essere considerata equivalente al 941 ° giorno dopo il 1 febbraio 1996. Con un'interpretazione rigorosa (non indulgente), tali date causeranno un'eccezione a essere gettato. Il valore predefinito è clemente.

+34

La mia domanda sarebbe, perché sulla terra è 'lenient' _true_ di default! Avrebbe avuto molto più senso per me se fosse _false_ di default, perché i programmatori, specialmente i principianti, tendevano a usare SDF come modo per verificare la validità della data, e aspettarsi una data "leniently parsable" per fallire (ma sarebbe passato). Il trattamento favorevole dovrebbe essere una funzione ** extra ** per coloro che lo comprendono e ** in realtà hanno bisogno di usarlo **. È ridicolo che gli sviluppatori Java abbiano deciso di renderlo un comportamento standard del sistema SDF, costringendo tutti gli altri a conoscere e utilizzare 'setLenient (false)'. Argh! ... – ADTC

+0

@ADTC: crea una factory che imposta i valori predefiniti appropriati per ogni componente che crei. – Atmocreations

+0

"un'eccezione": si deve leggere tale documentazione. Diavolo, voglio prenderlo, quindi dammi il tipo. Mi aspettavo che 'set()' generasse già un'eccezione. Invece, il metodo [getTime()] (https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getTime%28%29) lancia un IllegalArgumentException. –

10

Se la data non è indulgente, genera un errore se si passa la data di intervallo ma se non lo è, accetta e lo risolve. ad esempio, August 61st dal commento precedente diventerà il 30 settembre. Java doc su come impostarlo. L'impostazione predefinita è vera.

7

L'oggetto DateFormat è moderato per impostazione predefinita.

Leniency (Javadoc - Calendario)

Calendar ha due modi per interpretare i campi del calendario, indulgente e non indulgente. Quando un calendario è in modalità lenta, accetta un intervallo di valori di campo del calendario più ampio di di quello che produce.Quando un calendario ricalcola i valori del campo del calendario per il reso da get(), tutti i campi del calendario vengono normalizzati. Ad esempio, un indulgente GregorianCalendar interpreta MESE == GENNAIO, DAY_OF_MONTH == 32 come 1 ° febbraio

Quando un calendario è in modalità non-indulgente, viene generata un'eccezione se c'è qualche incongruenza nei suoi campi del calendario . Ad esempio, un GregorianCalendar produce sempre valori DAY_OF_MONTH tra 1 e la durata del mese. Un GregorianCalendar non indulgente genera un'eccezione al momento del calcolo dei valori del proprio tempo o del campo del calendario se è stato impostato un valore di campo fuori intervallo .

+2

@Binaya: non è necessario inviare messaggi di "ringraziamento" a tutti coloro che hanno aiutato. In realtà è * scoraggiato *. Semplicemente upvotare ogni risposta che ti ha aiutato (e opzionalmente accetta quello che ha aiutato di più). Vedi [le FAQ] (http://stackoverflow.com/questions/how-to-answer) (sezione Pay it forward). –

+2

@Joachim Sauer, un grazie non si scoraggia mai. –

+0

@TheEliteGentleman: non sono sicuro di essere d'accordo (* fa * aggiungere rumore), ma soprattutto è importante notare che al momento in cui ho postato questo commento questa risposta aveva zero upvotes (e l'OP aveva abbastanza rep per votare su). –

17

Il mio consiglio è quello di passare sempre indulgenti. Non riesco a pensare a un caso in cui desideri essere clemente e questa impostazione non dovrebbe mai essere l'impostazione predefinita per classi come SimpleDateFormat. L'elaborazione privilegiata può interpretare i dati inutili come stringhe temporali valide e apre errori che potrebbero essere difficili da individuare nei test. Inoltre, se si sta usando indulgente per tollerare variazioni nel formato temporale, si brucerà. Per esempio:

System.out.println(new SimpleDateFormat("yyyyMMdd").parse("2010-12-30")); 

rendimenti questo (il fuso orario può variare):

Mon Nov 02 00:00:00 EST 2009 

Questo risultato assurdo sembra essere la meno un mese ("-1"), secondo giorno ("2- ") del 2010. Il mese di zeroth è dicembre!

Sfortunatamente, l'utilizzo di setLenient (false) non conduce a un'interpretazione rigorosa del pattern. SimpleDateFormat tollera spazzatura seguendo il pattern match, come discusso qui:

SimpleDateFormat.parse() ignores the number of characters in pattern

Inoltre, non è rigorosa circa il numero di caratteri del modello, come ad esempio "d" al posto di "dd":

SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/d"); 
sdf.setLenient(false); 
System.out.println("For 5: " + sdf.parse("2010/01/5")); 
System.out.println("For 05: " + sdf.parse("2010/01/05")); 
System.out.println("For 15: " + sdf.parse("2010/01/15")); 

Resa:

For 5: Tue Jan 05 00:00:00 EST 2010 
For 05: Tue Jan 05 00:00:00 EST 2010 
For 15: Fri Jan 15 00:00:00 EST 2010 

anche con setLenient (false) "2010/01/05" è accettato con il modello "MM/dd yyyy /". E il disaccordo sui dati viene ignorato, come "1999/2011" con lo schema "yyyy/aaaa" (la risposta è il 2011).

L'utilizzo di SimpleDateFormat per convalidare le stringhe di data/ora è purtroppo inaffidabile. Se segui il link sopra vedrai alcune soluzioni, inclusa una versione più severa di SimpleDateFormat scritta da me!

2

Il trattamento si riferisce all'applicazione o meno di una regola rigorosa all'analisi . Se un oggetto DateFormat è indulgente, accetta Jan 32, 2005. In effetti, ci vorrà la libertà di convertirlo in 1 febbraio 2006. Per impostazione predefinita, un oggetto DateFormat è indulgente.

import java.text.DateFormat; 
import java.text.ParseException; 
import java.util.Date; 

public class MainClass { 
    public static void main(String[] args) { 
    DateFormat shortDf = DateFormat.getDateInstance(DateFormat.SHORT); 

    DateFormat mediumDf = DateFormat.getDateInstance(DateFormat.MEDIUM); 
    DateFormat longDf = DateFormat.getDateInstance(DateFormat.LONG); 
    DateFormat fullDf = DateFormat.getDateInstance(DateFormat.FULL); 
    System.out.println(shortDf.format(new Date())); 
    System.out.println(mediumDf.format(new Date())); 
    System.out.println(longDf.format(new Date())); 
    System.out.println(fullDf.format(new Date())); 

    // parsing 
    try { 
     Date date = shortDf.parse("Jan 32, 2005"); 
    } catch (ParseException e) { 
    } 
    } 
} 

E il risultato:

1/26/07 
Jan 26, 2007 
January 26, 2007 
Friday, January 26, 2007