将特定格式日期字符串转为Joda DateTime/Java Date时遇格式异常求助
日期字符串转Joda DateTime/Java Date失败的问题解决与最优方案
一、错误原因分析
1. Joda DateTime的问题
你的原Joda模式 "EEE MMM dd yyyy HH:mm:ss 'GMT'Z" 逻辑本身没问题,但漏掉了指定英文Locale。如果系统默认Locale不是英文,Joda无法解析Thu、May这类英文星期和月份缩写,直接就会抛出格式无效异常。另外要确保arrayHorarios里的日期字符串格式和模式完全匹配,没有多余空格或大小写偏差。
2. Java SimpleDateFormat的问题
你后来用的模式 "EEE MMM dd yyyy HH:mm:ss z" 里的z是用来匹配时区名称(比如GMT、CET),但你的日期字符串是GMT+0200,属于时区偏移量,应该用Z来匹配+0200部分,同时保留'GMT'字面量。而且同样需要指定Locale.ENGLISH,否则英文缩写解析会失败。
二、修复后的代码示例
1. Joda DateTime修复版
String pattern = "EEE MMM dd yyyy HH:mm:ss 'GMT'Z"; // 强制指定英文Locale,避免系统Locale干扰 DateTimeFormatter formatter = DateTimeFormat.forPattern(pattern).withLocale(Locale.ENGLISH); List<DateTime> dateTimeList = new ArrayList<>(); for (String horario : arrayHorarios) { DateTime dateTime = formatter.withOffsetParsed().parseDateTime(horario); dateTimeList.add(dateTime); // 如果需要转为Java Date Date javaDate = dateTime.toDate(); }
2. Java SimpleDateFormat修复版
ObjectMapper mapper = new ObjectMapper(); String[] arrayHorarios = mapper.readValue(horariosSave, String[].class); // 修正模式并指定英文Locale DateFormat df = new SimpleDateFormat("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.ENGLISH); List<Date> hor = new ArrayList<>(); try { for (int i = 0; i < arrayHorarios.length; i++) { System.out.println("Horario nº:"+i); System.out.println("String = "+arrayHorarios[i]); Date date = df.parse(arrayHorarios[i]); System.out.println("Date = " + df.format(date)); hor.add(date); } System.out.println("Clases guardadas:"+hor.size()); } catch (Exception e) { e.printStackTrace(); }
三、最简单的实现方案(推荐Java 8+)
Joda-Time已经被官方标记为过时,更推荐使用Java 8引入的java.time(JSR-310)API——它线程安全、功能完善,且JDBC 4.2+版本原生支持直接存入数据库,无需转成老旧的Date类。
代码示例
ObjectMapper mapper = new ObjectMapper(); String[] arrayHorarios = mapper.readValue(horariosSave, String[].class); // 定义格式器并指定英文Locale DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd yyyy HH:mm:ss 'GMT'Z", Locale.ENGLISH); List<OffsetDateTime> offsetDateTimeList = new ArrayList<>(); // 推荐用这个替代Date List<Date> dateList = new ArrayList<>(); // 仅当必须兼容旧API时使用 for (String horario : arrayHorarios) { // 解析为带时区偏移的日期时间对象 OffsetDateTime offsetDateTime = OffsetDateTime.parse(horario, formatter); offsetDateTimeList.add(offsetDateTime); // 如需转为Java Date(仅兼容旧代码场景) Date javaDate = Date.from(offsetDateTime.toInstant()); dateList.add(javaDate); } // 存数据库时,直接用OffsetDateTime即可(JDBC 4.2+支持) // 示例:preparedStatement.setObject(1, offsetDateTime);
关键注意点
- 必须指定
Locale.ENGLISH:因为日期字符串中的星期、月份是英文缩写,避免系统默认Locale(如中文)导致解析失败。 - 区分时区名称与偏移量:你的字符串是
GMT+0200属于偏移量,要用Z匹配,而不是匹配时区名称的z。 - 优先用
java.time:Joda-Time已停止维护,java.time是官方推荐的日期时间API,功能更强大且无历史遗留问题。
内容的提问来源于stack exchange,提问作者Jorge Antequera
相关产品推荐
相关产品推荐

