53

I'm a bit discouraged with parsing dates in Java 8 Time API.

Previously I could easily write:

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

But now if I use LocalDate and do it like this:

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

I receive an 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)

If I change string format to "yyyy-MM-dd" everything work perfectly, even without formatter:

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

So my question is: how to parse date in custom format using Java 8 Time API?

2 Answers 2

68

It makes sense: your input is not really a date because it does not have a day information. You should parse it as a YearMonth and use that result if you don't care about the day.

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

If you do need to apply a specific day, you can obtain a LocalDate from a YearMonth for example:

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

You can also use a TemporalAdjuster, for example, for the last day of the month*:

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

*with an import static java.time.temporal.TemporalAdjusters.lastDayOfMonth;

Sign up to request clarification or add additional context in comments.

2 Comments

That makes sense. If you are only representing a year and month (the exact date is irrelevant), then you only need to work with YearMonth. You don't need to convert it to LocalDate unlike pre-Java8 where we had to convert it to a default date of 1. :)
You can do LocalDate ld = ym.atEndOfMonth(); too.. Seriously, Java 8 Time API (JodaTime) is amazing :)
18

Following alternative is probably not so nice but at least a successfully tested solution, too, so I mention it here for completeness and as supplement to the right answer of @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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.