与 DateTimeFormatter 一起使用时,LocalTime 解析方法会引发错误

问题描述

基本上,我想将格式为 'hh:mm' 的 DateTimeFormatter 应用到我从 'zoneddatetime.toLocalTime()' 对象中获得的值并将其存储为 LocalTime 对象,以便我得到像 '08:00' 这样的值,下面的代码显示了我如何获取特定时区的当前时间,并且我尝试在格式化时将其转换为名为“currentTime”的 LocalTime:

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

        zoneddatetime zoneddatetime = zoneddatetime.Now(ZoneId.of(appTheme.getTimezone()));
        LocalTime currentTime = LocalTime.parse(zoneddatetime.toLocalTime().toString(),formatter);

现在由于某些未知原因,我从上面的最后一行代码中抛出了以下错误


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)

我希望我能很好地解释我的问题,我的主要目标是以“hh:mm”或“HH:mm”格式获取zoneddatetime.toLocalTime()”值并将其存储为LocalTime对象,我就可以实现它,因为出现错误

如果有人能帮忙就好了,干杯!

解决方法

tl;博士

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

或者只是:

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

详情

您的问题包括:

  • 您的格式模式 hh:mm 与您的输入 15:32:03.824 不匹配。
  • hh:mm 使用了错误的代码。 hh 表示 12 小时制,但您输入的显然是 24 小时制。

ISO 8601

您的输入格式符合时间的 ISO 8601 标准。

LocalTime

java.time 类在解析/生成文本时默认使用标准 ISO 8601 格式。所以不需要指定格式模式。只需解析为 LocalTime 对象。

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

您的更大目标尚不清楚,但我怀疑您想要在特定时区看到的当前时间。如果是这样,只需在传递时区时使用 LocalTime.now

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

如果您有一个表示为 ZonedDateTime 的时刻,只需调用 toLocalTime 即可提取 LocalTime 对象。

LocalTime lt = myZonedDateTime.toLocalTime() ;

提示:您似乎只考虑字符串操作。与其学习和使用 Java 8 及更高版本中内置的行业领先的 java.time 框架中的类的智能对象,不如考虑学习和使用这些类。请参阅 Oracle 免费提供的 Java Tutorial。注意上面的代码如何不使用字符串来完成它的工作。

截断

你说:

这样我就能得到像“08:00”这样的值,

如果您想将分钟和秒清除为零,请truncate

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

数据库

您评论了:

我需要将从“zonedDateTime.toLocalTime()”获得的值存储为“HH:mm”或“hh:mm”格式的LocalTime对象

如果您的意思是存储在数据库中,则您的数据库表应定义为类似于 SQL 标准类型 TIME 的类型,而不是文本类型。然后通过 JDBC 4.2 或更高版本传递您的 LocalTime 对象。

myPreparedStatement.setObject( …,lt ) ;

检索。

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

您评论了:

我将使用多个 LocalTime 值进行时间范围比较

使用一对 LocalTime 对象和 JDBC 查询类型为 TIME 的列。例如,让我们查找标记为午餐时间的行。

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

SQL 看起来像这样,其中 ? 是一个占位符,用于将值替换为 prepared statement 的一部分。

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

请注意,!< 的意思是“不小于”,是询问“等于或大于”的简短方式。

Java 代码为:

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

https://jwt.io/

如上述链接所述,您需要使用您选择的模式将时间格式化为字符串。请注意,hh 对应于 12 小时时间(即 AM/PM 时间),因此,您应该将 a 与它一起使用。查看You can NOT create a formatted Date-Time object了解更多详情。

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);
    }
}

输出:

21:40
09:40 PM