SimpleDateFormat.parse输出格式不符,存入MySQL DATETIME报错求助
问题分析与解决方案
首先,咱们先搞清楚你看到的format和parse输出差异的原因——这其实不是bug,只是Java对不同类型的输出逻辑不一样:
sdf.format(dt)返回的是按照你指定格式生成的字符串,也就是dd/MM/yyyy hh:mm:ss a,所以会显示23/05/2018 03:30:00 PM。sdf.parse(sdf.format(dt))返回的是一个Date对象,当你直接打印这个对象时,Java会调用它的toString()方法,这个方法的默认格式是EEE MMM dd HH:mm:ss zzz yyyy,所以才会显示Wed May 23 15:30:00 IST 2018。本质上这两个结果代表的是同一个时间点,只是展示形式不同而已。
接下来是你遇到的核心问题:存入MySQL时触发的Invalid Date Error。这是因为你可能尝试把dd/MM/yyyy hh:mm:ss a格式的字符串直接插入到DATETIME字段中,但MySQL的DATETIME类型只识别yyyy-MM-dd HH:mm:ss这种格式的字符串,或者更推荐的方式——直接传递日期时间对象给JDBC,而不是格式化后的字符串。
正确的解决方案
方案1:使用JDBC参数化查询(推荐,避免格式问题+防SQL注入)
不管用老API还是新API,直接传递日期时间对象给PreparedStatement是最稳妥的方式:
老API(java.util.Date)版本:
String ep = "a1527069600"; // 提取字符串中的时间戳数字部分 long epochSeconds = Long.parseLong(ep.substring(1)); // 转成JDBC支持的Timestamp对象 Timestamp dbTimestamp = new Timestamp(epochSeconds * 1000L); // 存入数据库的参数化查询 String sql = "INSERT INTO your_table (your_datetime_column) VALUES (?)"; PreparedStatement pstmt = yourDatabaseConnection.prepareStatement(sql); pstmt.setTimestamp(1, dbTimestamp); pstmt.executeUpdate();
新API(Java 8+ java.time包,推荐)
SimpleDateFormat和Date是线程不安全的,Java 8之后的java.time包解决了这些问题,用法更清晰:
String ep = "a1527069600"; long epochSeconds = Long.parseLong(ep.substring(1)); // 指定印度时区 ZoneId indiaZone = ZoneId.of("Asia/Calcutta"); // 从时间戳转成对应时区的LocalDateTime LocalDateTime dateTime = Instant.ofEpochSecond(epochSeconds) .atZone(indiaZone) .toLocalDateTime(); // JDBC 4.2+支持直接设置LocalDateTime String sql = "INSERT INTO your_table (your_datetime_column) VALUES (?)"; PreparedStatement pstmt = yourDatabaseConnection.prepareStatement(sql); pstmt.setObject(1, dateTime); pstmt.executeUpdate();
方案2:如果必须用字符串插入(不推荐)
如果你因为某些原因一定要用字符串插入,需要把日期转成MySQL识别的yyyy-MM-dd HH:mm:ss格式:
String ep = "a1527069600"; long epochSeconds = Long.parseLong(ep.substring(1)); Date dt = new Date(epochSeconds * 1000L); // 改用MySQL支持的格式 SimpleDateFormat mysqlSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); mysqlSdf.setTimeZone(TimeZone.getTimeZone("Asia/Calcutta")); String mysqlDateStr = mysqlSdf.format(dt); // 注意:尽量用参数化查询,不要直接拼接字符串到SQL里 String sql = "INSERT INTO your_table (your_datetime_column) VALUES (?)"; PreparedStatement pstmt = yourDatabaseConnection.prepareStatement(sql); pstmt.setString(1, mysqlDateStr); pstmt.executeUpdate();
总结
format和parse的输出差异只是展示形式不同,时间值是一致的;- 存入数据库报错的根源是格式不匹配,最安全的做法是直接传递日期时间对象给JDBC,而非格式化后的字符串;
- 优先使用Java 8+的
java.time包,避免老API的线程安全问题和设计缺陷。
内容的提问来源于stack exchange,提问作者Abhijeet Teli
相关产品推荐
相关产品推荐

