web-dev-qa-db-fra.com

Java 8 Time API: comment analyser la chaîne de format "MM.yyyy" vers LocalDate

Je suis un peu découragé par l'analyse des dates dans Java 8 Time API.

Auparavant, je pouvais facilement écrire:

String date = "04.2013";
DateFormat df = new SimpleDateFormat("MM.yyyy");
Date d = df.parse(date);

Mais maintenant, si j'utilise LocalDate et le fais comme ceci:

String date = "04.2013";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.yyyy");
LocalDate ld = LocalDate.parse(date, formatter);

Je reçois une exception:

Java.time.format.DateTimeParseException: Text '04' could not be parsed at index 0
Java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.Java:1948)
Java.time.format.DateTimeFormatter.parse(DateTimeFormatter.Java:1850)
Java.time.LocalDate.parse(LocalDate.Java:400)
Java.time.LocalDate.parse(LocalDate.Java:385)
com.luxoft.ath.controllers.JsonController.region(JsonController.Java:38)
Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
Sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.Java:62)
Sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.Java:43)
Java.lang.reflect.Method.invoke(Method.Java:483)
org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.Java:215)
org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.Java:132)
org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.Java:104)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandleMethod(RequestMappingHandlerAdapter.Java:749)
org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.Java:689)
org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.Java:83)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.Java:938)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.Java:870)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.Java:961)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.Java:852)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:617)
org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.Java:837)
javax.servlet.http.HttpServlet.service(HttpServlet.Java:723)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.Java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:107)

Si je change le format de chaîne en "aaaa-MM-jj" tout fonctionne parfaitement, même sans formateur:

String date = "2013-04-12";
LocalDate ld = LocalDate.parse(date);

Ma question est donc: comment analyser la date dans un format personnalisé en utilisant Java 8 Time API?

48
Maxim Kolesnikov

Cela a du sens: votre entrée n'est pas vraiment une date car elle n'a pas d'informations sur la journée. Vous devez l'analyser en tant que YearMonth et utiliser ce résultat si vous ne vous souciez pas de la journée.

String date = "04.2013";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.yyyy");
YearMonth ym = YearMonth.parse(date, formatter);

Si vous devez appliquer un jour spécifique, vous pouvez obtenir un LocalDate à partir d'un YearMonth par exemple:

LocalDate ld = ym.atDay(1);
//or
LocalDate ld = ym.atEndOfMonth();

Vous pouvez également utiliser un TemporalAdjuster, par exemple, pour le dernier jour du mois *:

LocalDate ld = ym.atDay(1).with(lastDayOfMonth());

*avec un import static Java.time.temporal.TemporalAdjusters.lastDayOfMonth;

55
assylias

L'alternative suivante n'est probablement pas aussi agréable, mais au moins une solution testée avec succès, aussi, je la mentionne ici pour être complète et comme complément à la bonne réponse de @assylias:

DateTimeFormatterBuilder builder = new DateTimeFormatterBuilder();
builder.parseDefaulting(ChronoField.DAY_OF_MONTH, 1);
builder.append(DateTimeFormatter.ofPattern("MM.yyyy"));
DateTimeFormatter dtf = builder.toFormatter();

String ym = "04.2013";
LocalDate date = LocalDate.parse(ym, dtf);
System.out.println(date); // output: 2013-04-01
15
Meno Hochschild