web-dev-qa-db-ja.com

Java 8 Time API:形式「MM.yyyy」の文字列をLocalDateに解析する方法

Java 8 Time APIで日付を解析することには少しがっかりしています。

以前は簡単に書くことができました:

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

しかし、今LocalDateを使用して、次のようにすると:

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

私は例外を受け取ります:

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)

文字列形式を"yyyy-MM-dd"に変更すると、フォーマッタがなくてもすべてが完全に機能します。

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

だから私の質問は:Java 8 Time APIを使用してカスタム形式で日付を解析する方法ですか?

48

それは理にかなっています:あなたの入力は実際には日付ではないので、日付ではありません。 YearMonthとして解析し、その日を気にしない場合はその結果を使用する必要があります。

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

特定の日を適用する必要がある場合は、LocalDateからYearMonthを取得できます。例:

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

たとえば、月の最後の日にTemporalAdjusterを使用することもできます*:

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

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

55
assylias

次の選択肢はおそらくそれほど素晴らしいものではありませんが、少なくともテストされたソリューションは成功しているので、ここで完全性と@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