Java SimpleDateFormat siempre regresa enero por mes

Estoy trabajando en tomar un valor de fecha (createWhen) de Active Directory y traducirlo en una fecha de Java, con el fin de obtener una lista de cuentas creadas entre dos fechas. Todo funciona bien, salvo por un método: el método donde voy desde la Fecha AD hasta la fecha Java. El método se ve así:

private Date getParsedDate(String givenString) { System.out.println("Value from AD is: " + givenString); Date parsedDate = null; String formattedString = this.formatDateString(givenString); System.out.println("Formatted String is: " + formattedString); SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/DD"); try { parsedDate = sdf.parse(formattedString); System.out.println("Final date string is: " + parsedDate.toString()); } catch (ParseException ex) { ex.printStackTrace(); } return parsedDate; } 

Y, para una sola pieza de datos arbitrarios de AD:

Value from AD is: 20050912190509.0Z

Formatted String is: 2005/09/12

Final date string is: Wed Jan 12 00:00:00 EST 2005

Obviamente, está recogiendo el día y el año correctamente (y si elijo incluir horas / minutos / segundos también los incluye correctamente), pero cada fecha se coloca en enero por algún motivo.

Ahora, estoy seguro de que mi error es bastante simple, pero he vuelto a revisar mi formato unas diez veces, y estoy en un punto en el que ya no puedo verlo más. ¿Puede un segundo par de ojos mirar con atención mi código y señalar dónde me equivoco para obtener el mes tan groseramente incorrecto?

Gracias.

Cambie la cadena del patrón de “aaaa / MM / DD” a “aaaa / MM / dd”

 SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd"); 

Asegúrese de no utilizar ‘mm’ en lugar de ‘MM’ o ‘MMM’. Como pequeña m denota minutos y las tapas M denota mes.

TL; DR

  LocalDate parsedDate = OffsetDateTime .parse("20050912190509.0Z", DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX")) .toLocalDate(); 

Esto produce un LocalDate de 2005-09-12 .

java.time

Estoy contribuyendo con la respuesta moderna. La respuesta de Suhas Phartale es correcta y fue una buena respuesta cuando fue escrita hace 7 años. Ahora, la clase SimpleDateFormat notoriamente problemática está obsoleta y tenemos mucho mejor en java.time , la moderna API de fecha y hora de Java. Recomiendo encarecidamente que use esto en lugar de las antiguas clases de fecha y hora.

Detalles

Parece que desde su código reformate su cadena de AD antes de analizarla. No hay necesidad de eso, la cadena de AD se puede analizar directamente. Podríamos haberlo analizado directamente en un LocalDate , pero recomiendo analizarlo en OffsetDateTime para tomar el tiempo y el desplazamiento de la cadena; como puede ver, esto se puede convertir directamente a LocalDate después. Un LocalDate es una fecha sin hora del día, por lo que parece coincidir con sus requisitos mejor que la antigua clase de Date .

La cadena está en UTC (denotada por Z al final). Lo anterior le da la fecha de la cadena, que es la fecha en UTC. Si, por el contrario, deseaba la fecha en que estaba en su zona horaria local cuando fue el 12 de septiembre a las 19:05 en hora UTC:

  LocalDate parsedDate = OffsetDateTime.parse(givenString, adDateTimeFormatter) .atZoneSameInstant(ZoneId.of("America/Coral_Harbour")) .toLocalDate(); 

Supuse que declaramos el formateador como un campo estático:

 private static final DateTimeFormatter adDateTimeFormatter = DateTimeFormatter.ofPattern("uuuuMMddHHmmss.SX"); 

En este caso, el resultado es el mismo, para otras zonas horarias no lo será. Sustituya su zona horaria deseada por America / Coral_Harbour. Para usar la configuración de zona horaria de la JVM, especifique ZoneId.systemDefault() . Tenga en cuenta, sin embargo, que la configuración puede ser modificada por otras partes de su progtwig u otros progtwigs que se ejecutan en la misma JVM, por lo que esto es frágil.

Y el punto de la respuesta de Suhas Phartale también es válido en java.time : las cadenas de patrones de formato distinguen entre mayúsculas y minúsculas, y necesitaba usar dd minúscula para el día del mes.

Tutorial

Obtenga más información sobre java.time en el tutorial de Oracle y / o busque otros recursos en la red.