如何修复错误 java.time.format.DateTimeParseException: Text '2021-07-24 18:11:33.0' could not be parsed, unparsed text found at index 19

问题描述

我将确认码链接发送到注册用户的电子邮件中,当点击链接时,我需要激活状态以便会员被批准,但我收到标题显示错误。一切都是完全真实的,但我无法理解为什么会发生这种情况。这是我的代码

1)在此代码部分,用户成为会员,并会向其电子邮件发送确认代码

@WebServlet(name = "RegisterUserSaveController",urlPatterns = {"/register-user-save"})
public class RegisterUserSaveController extends HttpServlet {
    
    protected void processRequest(HttpServletRequest request,HttpServletResponse response)
            throws servletexception,IOException {
        try {
            String name = request.getParameter("name");
            String surname = request.getParameter("surname");
            String email = request.getParameter("email");
            String password = request.getParameter("password");
            String repeatPassword = request.getParameter("password-repeat");
            
            if (!password.equals(repeatPassword)) {
                request.setAttribute("error","Password repeat is not same!");
                request.getRequestdispatcher("register").forward(request,response);
            } else {
                User user = new User();
                user.setName(name);
                user.setSurname(surname);
                user.setEmail(email);
                user.setPassword(PasswordHasher.hashPassword(password));
                String activationCode = UUID.randomUUID().toString();
                user.setActivationCode(MD5.hashedMd5(activationCode));
                LocalDateTime expiredDate = LocalDateTime.Now().plusHours(1);
                user.setExpiredDate(expiredDate);
                UserDaoService userDaoService = new UserDaoManager();
                userDaoService.save(user);
                
                String subject = "Confirm Registration";
                
                String link = "http://localhost:8084/employee/registerconfirm?code=" + activationCode;
                
                String title = "Your confirmation link:\n " + link;
                
                SendEmail.sendAsync(email,title,subject);
                
                request.setAttribute("info2","Your Registration was successfully! Pls check your email.");
                request.getRequestdispatcher("success-info").forward(request,response);
            }
        } catch (GeneralSecurityException e) {
            
        }

2)在此代码部分,执行用户单击发送到电子邮件链接后的步骤。所以如果代码正确,我会验证数据库用户的状态列。

@WebServlet(name = "RegisterConfirmController",urlPatterns = {"/registerconfirm"})
public class RegisterConfirmController extends HttpServlet {

    protected void processRequest(HttpServletRequest request,IOException {
        String code = request.getParameter("code");
        UserDaoService userDaoService = new UserDaoManager();
        if (code == null) {
            request.setAttribute("info1","Activation code is not correct!");
            request.getRequestdispatcher("error-info").forward(request,response);
        } else {
            code = MD5.hashedMd5(code);

            User user = userDaoService.findByActivationCode(code);

            if (user == null) {
                request.setAttribute("info1","Activation code is not correct!");
                request.getRequestdispatcher("error-info").forward(request,response);
            } else {
                LocalDateTime expiredDate = user.getExpiredDate();
                LocalDateTime currentDate = LocalDateTime.Now();

                if (expiredDate.isBefore(currentDate)) {
                    request.setAttribute("info1","Activation code is expired!");
                    request.setAttribute("info2","resend?id=" + user.getId() + "");
                    request.getRequestdispatcher("error-info").forward(request,response);

                } else if (user.getStatus() == UserStatusEnum.CONFIRMED.getValue()) {

                    request.setAttribute("info1","Your account already confirmed!");
                    request.getRequestdispatcher("error-info").forward(request,response);

                } else {

                    userDaoService.updateStatusById(user.getId(),UserStatusEnum.CONFIRMED);
                    request.setAttribute("info2","Your account is confirmed!");
                    request.getRequestdispatcher("success-info").forward(request,response);

                }

            }
        }
    }

3)但问题是,当我点击发送到电子邮件链接时,出现以下错误错误 java.time.format.DateTimeParseException: 无法解析文本 '2021-07-24 18:11:33.0',在索引 19 处找到未解析的文本

4)这是我与数据库相关的方法

@Override
    public User findByActivationCode(String activationCode) {
        try (Connection connection = DbConnection.getConnection()) {
            PreparedStatement preparedStatement = connection.prepareStatement("select id,expired_date,status from users where activation_code=?");
            preparedStatement.setString(1,activationCode);
            ResultSet resultSet = preparedStatement.executeQuery();
            if (resultSet.next()) {
                User user = new User();
                user.setId(resultSet.getInt(1));
                user.setExpiredDate(LocalDateTime.parse(resultSet.getString(2),DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
                user.setStatus(resultSet.getInt(3));
                return user;
            }
        } catch (Exception e) {
            System.out.println("findByActivationCode error " + e);
        }
        return null;
    }

解决方法

您必须决定如何处理 resultSet.getString(2) 返回的日期字符串中的“.0”。你可以做一个子字符串来删除它。或者您可以更改格式字符串以解决它。我为纳秒选择了“.n”,但您必须研究该值的含义。

再想一想,您甚至可能不想使用 resultSet.getString(2)。如果这是来自数据库的内容,您可能需要考虑返回时间戳的 resultSet.getTimestamp(2)。 可以在此处找到有关如何将其转换为 LocalDateTime 的信息 How to convert java.sql.timestamp to LocalDate (java8) java.time?

public static void main(String[] args)
{
  String text = "2021-07-24 18:11:33.0";
  //
  String text1 = text.substring(0,19);
  LocalDateTime ldt = LocalDateTime.parse(text1,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
  //
  LocalDateTime ldt2 = LocalDateTime.parse(text,DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.n"));

  int ai = 0;
}
,

您遇到问题是因为您错过了的模式。您可以使用以下模式:

u-M-d H:m:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]]

其中使用方括号将 fraction-of-second 设为可选。

演示:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern(
                "u-M-d H:m:s[.[SSSSSSSSS][SSSSSSSS][SSSSSSS][SSSSSS][SSSSS][SSSS][SSS][SS][S]]",Locale.ENGLISH);
        String strDateTime = "2021-07-24 18:11:33.0";
        LocalDateTime ldt = LocalDateTime.parse(strDateTime,dtf);
        System.out.println(ldt);
    }
}

输出:

2021-07-24T18:11:33

ONLINE DEMO

我还建议您将列类型更改为 Date-Time 类型,这将使​​您能够直接使用 java.time 类型而不是处理 String。查看 this answerthis answer 以了解如何将 java.time API 与 JDBC 结合使用。

Trail: Date Time 了解有关现代 Date-Time API 的更多信息。