用Java解析格式“2010年1月10日”的日期? (有序数指标,st | nd | rd | th)

时间:2011-01-18 09:10:00

标签: java date

我需要用Java解析格式“2010年1月10日”的日期。我怎么能这样做?

如何处理追踪日期编号的ordinal indicatorsstndrdth

4 个答案:

答案 0 :(得分:9)

这有效:

String s = "January 10th, 2010";
DateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy");
System.out.println("" + dateFormat.parse(s.replaceAll("(?:st|nd|rd|th),", "")));

但您需要确保使用正确的Locale来正确解析月份名称。

我知道你可以在SimpleDateFormat模式中包含一般文本。但是在这种情况下,文本依赖于信息,实际上与解析过程无关。

这实际上是我能想到的最简单的解决方案。但我希望被证明是错的。

您可以通过执行与此类似的操作来避免其中一条评论中出现的陷阱:

String s = "January 10th, 2010";
DateFormat dateFormat = new SimpleDateFormat("MMM dd yyyy");
System.out.println("" + dateFormat.parse(s.replaceAll("(?<= \\d+)(?:st|nd|rd|th),(?= \\d+$)", "")));

这样您就无法匹配Jath,uary 10 2010

答案 1 :(得分:1)

您可以将nd等设置为SimpleDateFormat中的文字。您可以定义所需的四种格式并尝试它们。首先从th开始,因为我猜这种情况会更频繁发生。如果它与ParseException失败,请尝试下一个。如果全部失败,则抛出ParseException。这里的代码只是一个概念。在现实生活中,您可能不会每次都生成新的格式,并且可能会考虑线程安全性。

public static Date hoolaHoop(final String dateText) throws ParseException
        {
        ParseException pe=null;
        String[] sss={"th","nd","rd","st"};
        for (String special:sss)
        {
        SimpleDateFormat sdf=new SimpleDateFormat("MMMM d'"+special+",' yyyy");

        try{
        return sdf.parse(dateText);
        }
        catch (ParseException e)
        {
        // remember for throwing later 
        pe=e;
        }
        }
        throw pe;
        }
        public static void main (String[] args) throws java.lang.Exception
        {
         String[] dateText={"January 10th, 2010","January 1st, 2010","January 2nd, 2010",""};
         for (String dt:dateText) {System.out.println(hoolaHoop(dt))};
        }

输出:

  

Sun 1月10日00:00:00 GMT 2010

     

Fri Jan 01 00:00:00 GMT 2010

     

2010年1月2日星期六00:00:00 GMT

     

线程“main”中的异常java.text.ParseException:Unparseable date:“”

"th","nd","rd","st"当然只适用于具有英语的语言环境。记在脑子里。在法国,我猜"re","nd"等。

答案 2 :(得分:1)

我想贡献现代的答案。而不是今天在两个投票最多的答案中使用的SimpleDateFormat类,您应该使用java.time(现代Java日期和时间API)。它提供了两个不错的解决方案。

简便解决方案

我们首先定义一个用于解析的格式化程序:

private static final DateTimeFormatter PARSING_FORMATTER = DateTimeFormatter.ofPattern(
        "MMMM d['st']['nd']['rd']['th'], uuuu", Locale.ENGLISH);

然后我们像这样使用它:

    String dateString = "January 10th, 2010";
    LocalDate date = LocalDate.parse(dateString, PARSING_FORMATTER);
    System.out.println("Parsed date: " + date);

输出为:

  

分析日期:2010-01-10

格式模式字符串中的方括号[]包含可选部分,单引号包含文字文本。因此,d['st']['nd']['rd']['th']意味着一个月的一天之后可能会有stndrd和/或th

更多固溶体

上述方法有两个局限性

  1. 它接受任何序号指示符,例如10st甚至10stndrdth
  2. 虽然格式化程序可用于解析,但是您不能将其用于格式化(它会提供January 10stndrdth, 2010)。

如果您想更好地验证序号指示器,或者希望将日期格式化回字符串,则可以通过以下方式构建格式化程序:

private static final DateTimeFormatter FORMATTING_AND_PARSING_FORMATTER;
static {
    Map<Long, String> ordinalNumbers = new HashMap<>(42);
    ordinalNumbers.put(1L, "1st");
    ordinalNumbers.put(2L, "2nd");
    ordinalNumbers.put(3L, "3rd");
    ordinalNumbers.put(21L, "21st");
    ordinalNumbers.put(22L, "22nd");
    ordinalNumbers.put(23L, "23rd");
    ordinalNumbers.put(31L, "31st");
    for (long d = 1; d <= 31; d++) {
        ordinalNumbers.putIfAbsent(d, "" + d + "th");
    }

    FORMATTING_AND_PARSING_FORMATTER = new DateTimeFormatterBuilder()
            .appendPattern("MMMM ")
            .appendText(ChronoField.DAY_OF_MONTH, ordinalNumbers)
            .appendPattern(", uuuu")
            .toFormatter(Locale.ENGLISH);
}

这将解析与上面相同的日期字符串。我们还要尝试进行格式化:

    System.out.println("Formatted back using the same formatter: "
            + date.format(FORMATTING_AND_PARSING_FORMATTER));
  

使用相同的格式化程序重新格式化:2010年1月10日

链接

答案 3 :(得分:0)

这是另一种简单的方法,但需要包含 apache commons jar

import org.apache.commons.lang.time.*;

String s = "January 10th, 2010";
String[] freakyFormat = {"MMM dd'st,' yyyy","MMM dd'nd,' yyyy","MMM dd'th,' yyyy","MMM dd'rd,' yyyy"};
DateUtils du = new DateUtils();
System.out.println("" + du.parseDate(s,freakyFormat));