Moment.js生成的日期格式在Java中解析抛出异常问题求助
Hey there! Let's break down exactly what's going wrong here and get your date parsing working smoothly.
The Core Issue
Your Moment.js code outputs dates with ordinal suffixes (like 30th instead of just 30), but the SimpleDateFormat pattern you're using ("MMM dd, yyyy hh:mm:ss a") only expects plain numeric dates. The dd format can't recognize th/st/nd/rd—that's the root cause of your parse exception.
Quick Fixes & Best Practices
First off: I'd strongly recommend using Java 8+'s java.time library instead of SimpleDateFormat—it's thread-safe, more flexible, and not outdated. But I'll cover solutions for both approaches to fit your project needs.
Solution 1: Parse Directly with Java 8+ DateTimeFormatter (Handle Ordinal Suffixes)
We can build a custom formatter that understands those ordinal suffixes natively:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.time.format.DateTimeFormatterBuilder; import java.time.temporal.ChronoField; import java.util.HashMap; import java.util.Locale; public class OrdinalDateParser { public static void main(String[] args) { String momentGeneratedDate = "May 30th 2018, 11:38:58 am"; // Build a formatter that recognizes ordinal day suffixes DateTimeFormatter formatter = new DateTimeFormatterBuilder() .appendPattern("MMMM ") // Map each day to its ordinal string (1st, 2nd, etc.) .appendText(ChronoField.DAY_OF_MONTH, new HashMap<>() {{ // Handle special case days put(1, "1st"); put(2, "2nd"); put(3, "3rd"); put(21, "21st"); put(22, "22nd"); put(23, "23rd"); put(31, "31st"); // All other days use the "th" suffix for (int i = 4; i <= 30; i++) { if (i != 21 && i != 22 && i != 23) { put(i, i + "th"); } } }}) .appendPattern(" yyyy, hh:mm:ss a") .toFormatter(Locale.US); LocalDateTime parsedDateTime = LocalDateTime.parse(momentGeneratedDate, formatter); System.out.println(parsedDateTime); // Output: 2018-05-30T11:38:58 } }
Solution 2: Strip Ordinal Suffixes First (Simpler Approach)
If you don't want to build a custom formatter, just use regex to remove the suffixes before parsing:
Option A: For Legacy Code (Using SimpleDateFormat)
Only use this if you're stuck on Java 7 or earlier:
import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Locale; import java.util.regex.Pattern; public class LegacyDateFix { public static void main(String[] args) throws ParseException { String momentDate = "May 30th 2018, 11:38:58 am"; // Regex to strip st/nd/rd/th from the date number String cleanedDate = Pattern.compile("(\\d+)(st|nd|rd|th)") .matcher(momentDate) .replaceAll("$1"); // Now parse with a matching pattern SimpleDateFormat dateFormat = new SimpleDateFormat("MMMM dd yyyy, hh:mm:ss a", Locale.US); System.out.println(dateFormat.parse(cleanedDate)); // Output: Wed May 30 11:38:58 CST 2018 } }
Option B: Recommended (Java 8+ DateTimeFormatter)
Clean the string first, then parse with the modern, safer API:
import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.Locale; import java.util.regex.Pattern; public class CleanDateParser { public static void main(String[] args) { String momentDate = "May 30th 2018, 11:38:58 am"; // Remove ordinal suffixes from the date String cleanedDate = Pattern.compile("(\\d+)(st|nd|rd|th)") .matcher(momentDate) .replaceAll("$1"); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM dd yyyy, hh:mm:ss a", Locale.US); LocalDateTime parsedDateTime = LocalDateTime.parse(cleanedDate, formatter); System.out.println(parsedDateTime); // Output: 2018-05-30T11:38:58 } }
A Quick Best Practice Tip
Avoid SimpleDateFormat whenever you can—it's not thread-safe and has a lot of hidden quirks. The java.time library (or Joda-Time for Java 7 projects) is the standard for reliable date/time operations in Java now.
内容的提问来源于stack exchange,提问作者K Guru

