2011-09-30 22 views
43

Aquí lenient se utiliza en Java DateFormat. Revisé el documento, pero no entendí lo que decía.¿Cuál es el uso de "indulgente"?

¿Puede algún cuerpo decirme cuál es el uso de este lenient, con un ejemplo en tiempo real donde lo usamos?

+1

FYI, 'DateFormat' es una de las clases de fecha y hora viejas problemáticas que ahora son legado, suplantado por las clases java.time. Utilice ['java.time.format.DateTimeFormatter'] (https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html) en su lugar. –

Respuesta

4

Puede establecer el analizador de fecha como no indulgente si desea que acepte estrictamente un formato de fecha que proporcionó. Está bien explicado en the doc:

Por defecto, el análisis sintáctico es indulgente: Si la entrada no está en la forma utilizada por el método de formato de este objeto, pero todavía se puede analizar como una fecha, entonces el análisis sintáctico tiene éxito. Los clientes pueden insistir en el estricto cumplimiento del formato llamando al setLenient(false).

20

Por ejemplo esto:

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

resultados en:

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

Por qué el código siguiente está funcionando. ? SimpleDateFormat simpleDateFormat = new SimpleDateFormat ("yyyy"); \t \t \t System.out.println (simpleDateFormat.parse ("4")); \t \t \t simpleDateFormat.setLenient (falso); \t \t \t System.out.println (simpleDateFormat.parse ("4")); – KSHiTiJ

+0

Causa (en el calendario gregoriano que es el valor predeterminado de Java) no es un año "0". Después de 1 aC (que se traduciría en -1 AFAIK) sigue a 1 AD (que es, bueno, 1). Por lo tanto, "0" arriba se trata (indulgentemente) como "0 años (después del primer año, que es 1)" y resulta en 1. Si el análisis indulgente está desactivado, se lanza la excepción. En otras palabras, no verifica la entrada de 4 dígitos bien formateada con ese código. (Incluso el 300 dC, "300" sería un año válido, por supuesto) – chammp

40

El javadoc establece claramente:

Especificar si es o no la fecha/hora del análisis es que sea indulgente . Con análisis indulgente, el analizador puede usar heurísticas para interpretar las entradas que no coinciden exactamente con el formato de este objeto. Con un análisis estricto, las entradas deben coincidir con el formato de este objeto.

Por lo tanto, si usted tiene un patrón y crear un objeto Date que estrictamente coincide con su patrón, establecer indulgente con false. Además, DateFormat es indulgente, por defecto.

Básicamente, DateFormat conjuntos Calendar.setLenient y los estados Javadoc:

Especifica si la interpretación de fecha/hora es ser indulgente. Con una interpretación indulgente, una fecha como "febrero 942, 1996" será tratada como equivalente al día 941 después del 1 de febrero, 1996. Con interpretación estricta (no indulgente), tales fechas causarán una excepción a ser arrojado. El valor predeterminado es indulgente.

+34

Mi pregunta sería, ¿por qué es "indulgente" _de valor predeterminado? Tendría mucho más sentido para mí si fuera "falsa" por defecto, porque los programadores, especialmente los principiantes, tenderían a usar SDF como una forma de verificar la validez de la fecha, y esperar una fecha de "indulgencia permisible" para fallar (pero pasaría) La clemencia debe ser una característica ** extra ** para aquellos que la entienden y ** realmente necesitan usarla **. Es ridículo que los desarrolladores de Java decidieran convertirlo en un comportamiento estándar del sistema SDF, forzando a todos a aprender y usar 'setLenient (false)'. Argh! ... – ADTC

+0

@ADTC: crea una fábrica que establezca tus propios valores predeterminados adecuados para cada componente que crees. – Atmocreations

+0

"una excepción" - debe gustar dicha documentación. Demonios, quiero atraparlo, así que dame el tipo. Esperaba que 'set()' arrojara una excepción. En cambio, el método [getTime()] (https://docs.oracle.com/javase/7/docs/api/java/util/Calendar.html#getTime%28%29) arroja una IllegalArgumentException. –

10

Si la fecha no es indulgente, arrojará un error si pasa la fecha fuera del rango, pero si no lo está aceptará y lo arreglará. Por ejemplo, August 61st del comentario anterior será el 30 de septiembre. Java doc sobre cómo configurarlo. El valor predeterminado es verdadero

7

El objeto DateFormat es indulgente por defecto.

Leniency (Javadoc - Calendario)

calendario tiene dos modos de interpretación de los campos de calendario, indulgentes y no permisivas. Cuando un calendario está en modo indulgente, acepta un rango más amplio de valores de campo de calendario que el que produce.Cuando un calendario vuelve a calcular los valores de campo de calendario para return by get(), todos los campos de calendario se normalizan. Por ejemplo, una leve GregorianCalendar interpreta MES == ENERO DAY_OF_MONTH == 32 como 1 de febrero

Cuando un calendario es en modo no indulgente, se lanza una excepción si hay alguna inconsistencia en sus campos de calendario . Por ejemplo, un calendario GregorianCalendar siempre produce valores DAY_OF_MONTH entre 1 y la longitud del mes. Un GregorianCalendar no indulgente lanza una excepción al calcular sus valores de tiempo o en el campo de calendario en su caso valor de campo fuera de la gama se ha establecido.

+2

@Binaya: no necesita enviar mensajes de "agradecimiento" a todos los que ayudaron. De hecho, está * desalentado *. Simplemente resuma cada respuesta que le ayudó (y opcionalmente acepte la que más le ayudó). Consulte [las preguntas más frecuentes] (http://stackoverflow.com/questions/how-to-answer) (sección Pagar hacia adelante). –

+2

@Joachim Sauer, un agradecimiento nunca se desalienta. –

+0

@TheEliteGentleman: No estoy seguro de estar de acuerdo (* hace * agregar ruido), pero lo más importante es que debe tenerse en cuenta que en el momento en que publiqué este comentario, esta respuesta tenía cero votos ascendentes (y el OP tenía suficientes representantes para votar arriba). –

17

Mi consejo es apagar siempre indulgente. No puedo pensar en un caso en el que desee indulgencia, y esta configuración nunca debería haber sido la predeterminada para clases como SimpleDateFormat. El procesamiento lento puede interpretar la basura como cadenas de tiempo válidas y abre errores que pueden ser difíciles de detectar en las pruebas. Además, si usa indulgencia para tolerar variaciones en el formato de tiempo, se quemará. Por ejemplo:

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

Rendimientos este (su zona de tiempo puede variar):

Mon Nov 02 00:00:00 EST 2009 

Este resultado absurdo parece ser el menos uno mes ("-1"), segundo día ("2- ") de 2010. ¡El mes cero es diciembre!

Desafortunadamente, el uso setLenient (falso) no conduce a una estricta interpretación del patrón. SimpleDateFormat va a tolerar la basura después de la coincidencia de patrón, como se discute aquí:

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

Además, no es estricto en cuanto al número de caracteres de patrones, tales como "d" en lugar de "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")); 

Rendimiento:

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 

también con setLenient (false) "01.05.2010" se acepta con el patrón "aaaa/MM/dd". Y el desacuerdo de datos se ignora, como "1999/2011" con el patrón "aaaa/aaaa" (la respuesta es 2011).

Usando SimpleDateFormat para validar las cadenas de fecha/hora es tristemente poco fiable. Si sigues el enlace de arriba, verás algunas soluciones, incluida una versión más estricta de SimpleDateFormat escrita por mí.

2

cooperación se refiere a si o no una regla estricta se aplicará en análisis. Si un objeto DateFormat es indulgente, aceptará Jan 32, 2005. De hecho, se tomará la libertad de convertirlo al 1 de febrero de 2006. Por defecto, un objeto DateFormat es 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) { 
    } 
    } 
} 

Y el resultado:

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