Java 8 Time API:如何将格式为"MM.yyyy"的字符串解析为LocalDate

Max*_*kov 48 java date java-8 java-time

我对Java 8 Time API中的日期解析感到有点气馁.

以前我可以轻松写:

String date = "04.2013";
DateFormat df = new SimpleDateFormat("MM.yyyy");
Date d = df.parse(date);
Run Code Online (Sandbox Code Playgroud)

但是现在如果我使用LocalDate并像这样做:

String date = "04.2013";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.yyyy");
LocalDate ld = LocalDate.parse(date, formatter);
Run Code Online (Sandbox Code Playgroud)

我收到一个例外:

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)
Run Code Online (Sandbox Code Playgroud)

如果我将字符串格式更改为"yyyy-MM-dd",即使没有格式化程序,一切也能正常工作:

String date = "2013-04-12";
LocalDate ld = LocalDate.parse(date);
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:如何使用Java 8 Time API以自定义格式解析日期?

ass*_*ias 56

这是有道理的:您的输入不是真正的日期,因为它没有日期信息.YearMonth如果你不关心这一天,你应该将其解析为a 并使用该结果.

String date = "04.2013";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM.yyyy");
YearMonth ym = YearMonth.parse(date, formatter);
Run Code Online (Sandbox Code Playgroud)

如果您确实需要申请特定日期,您可以LocalDateYearMonth例如:

LocalDate ld = ym.atDay(1);
//or
LocalDate ld = ym.atEndOfMonth();
Run Code Online (Sandbox Code Playgroud)

TemporalAdjuster例如,您也可以使用一个月的最后一天*:

LocalDate ld = ym.atDay(1).with(lastDayOfMonth());
Run Code Online (Sandbox Code Playgroud)

*与 import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;

  • 你可以做`LocalDate ld = ym.atEndOfMonth();`太......说真的,Java 8 Time API(JodaTime)很棒`:)` (4认同)
  • 那讲得通.如果您只代表一年和一个月(确切的日期无关紧要),那么您只需要使用`YearMonth`.与Java8之前不同,你不需要将它转换为`LocalDate`,我们必须将它转换为*1的默认*日期.`:)` (2认同)

Men*_*ild 15

以下替代方案可能不是那么好,但至少也是一个成功测试的解决方案,所以我在这里提到完整性并作为@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
Run Code Online (Sandbox Code Playgroud)