Yeshan Santhush
Yeshan Santhush

Reputation: 75

LocalTime parse method throws error when used with DateTimeFormatter

Basically im want to apply a DateTimeFormatter with format 'hh:mm' to the value i get from 'zonedDateTime.toLocalTime()' object and store it as a LocalTime object, so that i get values like '08:00', the below code shows how i get the current time of a specific timezone, and im trying to convert it to a LocalTime called 'currentTime' while formatting it:

        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("hh:mm");

        ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.of(appTheme.getTimezone()));
        LocalTime currentTime = LocalTime.parse(zonedDateTime.toLocalTime().toString(),formatter);

Now for some unknown reason i get the below error thrown from the last code line from above:


java.time.format.DateTimeParseException: Text '15:32:03.824' could not be parsed, unparsed text found at index 5
    java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:1952)
    java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1851)
    java.time.LocalTime.parse(LocalTime.java:441)
    io.apptizer.cafe.controller.CategoryController.getBusinessCategoryDetails(CategoryController.java:789)
    io.apptizer.cafe.controller.CategoryController.backwardCompatibilityCategories(CategoryController.java:387)
    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:498)
    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:781)
    org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:721)
    org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:83)
    org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:943)
    org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:877)
    org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:966)
    org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:857)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:622)
    org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:842)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
    org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    io.apptizer.cafe.filter.SessionHandleFilter.doFilter(SessionHandleFilter.java:39)

I hope i explained my problem well, my main goal is to get the 'zonedDateTime.toLocalTime()' value in 'hh:mm' or 'HH:mm' format and store it as a LocalTime object, i just can achieve it because is error comes up,

would be good if someone can help, cheers!

Upvotes: 0

Views: 1232

Answers (2)

Arvind Kumar Avinash
Arvind Kumar Avinash

Reputation: 79620

You can NOT create a formatted Date-Time object

As described in the above link, you need to format the time into the string with the pattern of your choice. Note that hh corresponds to 12-hour time (i.e. AM/PM time) and therefore, you should use a with it. Check the documentation for more details.

import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter24Hour = DateTimeFormatter.ofPattern("HH:mm", Locale.ENGLISH);
        DateTimeFormatter formatterAmPm = DateTimeFormatter.ofPattern("hh:mm a", Locale.ENGLISH);

        ZonedDateTime zonedDateTime = ZonedDateTime.now(ZoneId.systemDefault());
        LocalTime localTime = zonedDateTime.toLocalTime();
        
        String currentTime24HourFormat = formatter24Hour.format(localTime);
        String currentTime12HourFormat = formatterAmPm.format(localTime);

        System.out.println(currentTime24HourFormat);
        System.out.println(currentTime12HourFormat);
    }
}

Output:

21:40
09:40 PM

Upvotes: 1

Basil Bourque
Basil Bourque

Reputation: 340200

tl;dr

ZonedDateTime
.now(
    ZoneId.of( "Asia/Tokyo" )
)
.toLocalTime()

Or just:

LocalTime.now( ZoneId.of( "Asia/Tokyo" ) )

Details

Your problems include:

  • Your formatting pattern hh:mm does not match your input 15:32:03.824.
  • hh:mm is using the wrong codes. The hh means 12-hour clock, but your input is clearly 24-hour clock.

ISO 8601

Your input format complies with the ISO 8601 standard for a time-of-day.

LocalTime

The java.time classes use standard ISO 8601 formats by default when parsing/generating text. So no need to specify a formatting pattern. Just parse as a LocalTime object.

LocalTime lt = LocalTime.parse( "15:32:03.824" ) ;

Your larger goal is unclear, but I suspect you want the current time-of-day as seen in a particular time zone. If so, just use LocalTime.now while passing the time zone.

ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalTime lt = LocalTime.now( z ) ;

If you have a moment represented as a ZonedDateTime, simply call toLocalTime to extract a LocalTime object.

LocalTime lt = myZonedDateTime.toLocalTime() ;

Tip: You seem to be caught in thinking only in terms of string manipulations. Think instead of learning and using smart objects of the classes found in the industry-leading java.time framework built into Java 8 and later. See the Java Tutorial by Oracle, free-of-cost. Notice how the code above uses no strings to do its work.

Truncating

You said:

so that i get values like '08:00',

If you mean you want to clear the minutes and seconds to zero, truncate.

LocalTime lt = LocalTime.now( ZoneId.of( "America/Edmonton" ) ).truncatedTo( ChronoUnit.HOURS ) ;

Database

You commented:

i need to store the value i get from 'zonedDateTime.toLocalTime()' as a LocalTime object in 'HH:mm' or 'hh:mm' format

If you mean store in a database, your database table should be defined as the type akin to the SQL-standard type TIME rather than a textual type. Then pass your LocalTime object via JDBC 4.2 or later.

myPreparedStatement.setObject( … , lt ) ;

Retrieval.

LocalTime lt = myResultSet.getObject( … , LocalTime.class ) ;

You commented:

i will be using multiple LocalTime values for time range comparisons

Use a pair of LocalTime objects with JDBC to query columns of type TIME. For example, let's look for rows that are marked for the lunch hour.

LocalTime start = LocalTime.NOON ;
LocalTime end = LocalTime.of( 13 , 0 ) ;

The SQL would look something like this, where ? is a placeholder for a value to be substituted as part of a prepared statement.

SELECT * 
FROM some_table_
WHERE time_of_day_ !< ? 
AND time_of_day_ < ? 
; 

Notice that !<, meaning "is not less than", is a shorter way of asking "is equal to or greater than".

Java code would be:

myPreparedStatement.setObject( 1 , start ) ;
myPreparedStatement.setObject( 2 , end ) ;

Upvotes: 2

Related Questions