2012-05-15 15 views
7

Así que estoy usando dateString1.compareTo(dateString2) que hace una comparación lexicográfica con cadenas, basado en el valor Unicode de cada carácter, y devuelve un int. Aquí hay una muestra de código.Comparando cadenas de fechas en Java

String dateString1 = "05-12-2012"; 
String dateString2 = "05-13-2012"; 
if (dateString1.compareTo(dateString2) <=0){ 
    System.out.println("dateString1 is an earlier date than dateString2"); 
} 

¿Es este un enfoque incorrecto para comparar fechas en Java?

En mis pruebas, no me he encontrado en una situación en la que haya obtenido resultados inesperados. Realmente no quiero crear un objeto Date fuera de la cadena, si no es necesario, porque estoy haciendo esto dentro de un bucle de ejecución larga.

Ninja Editar Espigando partir de las respuestas de abajo no hay nada de malo en la comparación de fechas como una cadena si está en formato yyyyMMdd pero si lo es en cualquier otro formato es obvio que da lugar a error.

De hecho, tengo mi cadena de fecha como formato yyyyMMdd en mi código actual. (Escribí el formato incorrecto en el ejemplo que di más arriba). Por lo tanto, por ahora, dejaré el código tal como está, y agregaré algunas líneas de comentarios para justificar mi decisión.

Pero ahora veo que comparar cadenas de este tipo es muy limitante y me toparé con errores si dba decide cambiar el formato de fecha en el futuro, lo cual no veo que ocurra.

+2

echar un vistazo a esta pregunta hecha por mí hace algún tiempo http://stackoverflow.com/questions/2592501/compare-dates-in-java – ant

Respuesta

8

Le sugiero que haga lo correcto (as described here) y convertir a objetos adecuados Date para comparar. Preocuparse por el impacto en el rendimiento si y realmente impacta su aplicación (que probablemente no lo hará).

+2

Excepto en 2017 (y en adelante), conviértalo en 'LocalDate' en su lugar (' Date' fue una buena elección en 2012, ya hace tiempo que está desactualizado). –

4

Es bastante malo ya que ahora no puede manejar un cambio de año.

Si así lo desea, puede formatear la fecha como YYYY-MM-DD para que el año nuevo no la arruine.

+1

Cualquier enfoque que sugiere la comparación de fechas como cadenas merece un par de puñetazos amistosos! :) – Alfabravo

+3

YYYYMMDD se puede comparar como cadenas. –

17

Usar cadenas para manejar fechas en Java no siempre es la mejor opción. Por ejemplo, cuando es un salto de año, febrero tiene un día adicional. Debido a que las cadenas pueden ser aparentemente correctas, es más apropiado realizar una conversión . Java valida que la fecha sea correcta.

Puede convertir cadenas a fechas usando la clase SimpleDateFormat.

public static void main(String[] args) throws ParseException { 
    String dateString1 = "05-12-2012"; 
    String dateString2 = "05-13-2012"; 

    SimpleDateFormat format = new SimpleDateFormat("dd-MM-yyyy"); 

    Date date1 = format.parse(dateString1); 
    Date date2 = format.parse(dateString2); 

    if (date1.compareTo(date2) <= 0) { 
     System.out.println("dateString1 is an earlier date than dateString2"); 
    } 
} 

Para saber en qué parámetros se les permite comprobar Customizing Formats (The Java™ Tutorials > Internationalization > Formatting)

+0

¿Has probado este código? –

+0

Sí, las impresiones 'dateString1 es una fecha anterior a dateString2'. ¿Hay algún problema con el código? –

+0

Las cadenas de fecha están en una forma diferente que el constructor SimpleDateFormat. –

1

si usted está haciendo una sola lectura de cada fecha a continuación AAAAMMDD (no MMDDAAAA como lo hizo) podría ser la solución más óptima. sin embargo, cuando tiene la intención de procesar cada fecha más de una vez (por ejemplo, las está ordenando), entonces es mejor cambiarlas a un objeto que se pueda comparar más rápido que la cadena (p. ej.fecha)

2

Es malo usar las reglas para la alfabetización para manejar la fecha de pedido, sobre todo porque se encuentra con problemas donde las cosas están clasificadas de manera diferente de acuerdo con el alfabeto y el sistema numérico

Para el alfabeto

01-02-2011 comes before 
01-1-2011 (because 0 in the date field is before 1 in the other date field) 

para el sistema de numeración

01, 02, 2011 comes after 
01, 1, 2011 because all fields are being compared like numbers 

objetos Date extienden comparación numérica saber qué campos prevalecer en el COMPARACIÓN n, por lo que no obtiene un mes anterior poniendo una fecha "anterior" a otra que realmente ocurre en un último mes pero un año anterior.

Si tiene un control estricto sobre el formato de fecha, puede alinear las fechas de manera que también sigan las reglas alfabéticas; sin embargo, hacerlo corre el riesgo de que su programa entero falle de formas extrañas si accidentalmente inyecta una fecha mal formateada.

La forma típica de hacer esto es (no se recomienda, por favor utilice las aplicaciones comparaciones que no sean String)

YYYYMMDD 
(year)(month)(day) all zero-padded. 

Se incluye la última técnica principalmente como es muy probable que verlo en su hábitat natural, y debe reconocerlo por lo que es: un intento de manejar las fechas sin una biblioteca de fecha adecuada (también conocido como un truco inteligente).

+0

Gracias. ¿Podría darnos una referencia para la última parte? Este caso me funciona muy bien, pero solo quiero asegurarme de que la lógica sea plena prueba – ShikharDua

1

Como se discutió, generalmente es mejor trabajar con objetos de fecha y hora que con cadenas.

java.time

las otras respuestas utilizan las clases de fecha y hora anticuadas viejos que han demostrado ser mal diseñado, confuso y problemático. Carecen de una clase para representar realmente un valor de fecha solamente sin hora del día y sin zona horaria.

En su lugar, utilice el marco java.time integrado en Java 8 y posterior. Ver Oracle Tutorial. Gran parte de la funcionalidad de java.time se transfiere a Java 6 & 7 en ThreeTen-Backport y se adapta a Android en ThreeTenABP.

String input = "05-12-2012"; 
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM-dd-yyyy"); 
LocalDate ld = LocalDate.parse(input , formatter); 

El LocalDate implementa compareTo. Además, puede llamar a los métodos iguales, isBefore, isAfter.

Boolean isEarlier = ld.isBefore(someOtherLocalDate);