在Java中解析字符串中的不同日期格式

5

我可以提供一个字符串,其中可能包含以下任意一种格式的日期:

2001-01-05 (yyyy-mm-dd)
2001/01/05 (yyyy/mm/dd)
01/05/2001 (dd/mm/yyyy)
01-05-2001 (dd-mm-yyyy)
2001 january 5
2001 5 january
january 5 2001
5 january 2001
january 5
5 january

我希望能够解析特定的字符串并从中提取出日期对象。

我的方法如下:

String[] date_formats = {
                            "yyyy-MM-dd",
                            "yyyyy/MM/dd", 
                            "dd/MM/yyyyy",
                            "dd-MM-yyyy",
                            "yyyy MMM dd",
                            "yyyy dd MMM",
                            "dd MMM yyyy",
                            "dd MMM",
                            "MMM dd",
                            "dd MMM yyyy"};

String output_date = null;
for (String formatString : date_formats)
{
     try
     {    
         Date mydate = new SimpleDateFormat(formatString).parse(token);
         SimpleDateFormat outdate = new SimpleDateFormat("yyyyMMdd");
         output_date = outdate.format(mydate);
         break;
     }
     catch (ParseException e) {
         System.out.println("Next!");
     }
 }

这似乎不能按预期工作,尤其是对于像2001年1月5日这样的日期。我该如何解决这个问题?


@Kayaman,这些模式有什么问题吗?http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html - Alagappan Ramu
1
当您想要解析特定语言的日期时,请始终提供日期格式的区域设置。(new SimpleDateFormat("{format}", Locale.ENGLISH);) - Arnaud Denoyelle
@AlagappanRamu 现在没有问题了,因为你已经修复了它们。 - Kayaman
@Kayaman 对于像2001年1月5日这样的日期仍然无法正常工作。它满足yyyy MMM dd模式,但我最终得到的日期是00100624,这完全是任意的。 - Alagappan Ramu
这似乎不按预期工作。你是否遇到了异常或者日期看起来不正确?如果有例子会更好。 - Arnaud Denoyelle
8个回答

6

使用SimpleDateFormat.setLenient(false)。这样它就不会尝试解析不是它想要的确切格式的日期。


虽然这个信息很有用,但在这种情况下却无用。原帖作者正在尝试使用try/catch语句中的每种格式,直到达到try语句的结尾。 - Arnaud Denoyelle
1
@ArnaudDenoyelle 无用?他的问题是在某些情况下,非正确模式正在解析值,给出任意值。通过将宽松设置为false来纠正这种情况。 - Kayaman
在我看来,不正确的模式将在catch语句中结束,并尝试下一个模式。 - Arnaud Denoyelle
@ArnaudDenoyelle 这对我在解析日期时避免误报非常有帮助。 - Alagappan Ramu
好的,我对lenient的含义有些困惑。给Kayaman加1分。 - Arnaud Denoyelle

1

你需要在date_formats数组中拥有所有格式,以适应你预期的日期格式类型。

查看SimpleDateFormat javadocs

查看javadocs中的示例。

2001-01-05      - yyyy-MM-dd 
2001/01/05      - yyyy/MM/dd
01/05/2001      - dd/MM/yyyy 
01-05-2001      - dd-MM-yyyy 
2001 january 5  - yyyy MMMMM d
2001 5 january  - yyyy d MMMMM
january 5 2001  - MMMMM d yyyy 
5 january 2001  - d MMMMM yyyy
january 5       - MMMMM d
5 january       - d MMMMM

我已经查看了文档。我提到的模式不正确吗? - Alagappan Ramu
1
是的。你的格式不正确。我已经添加了你需要的格式。 - JHS
它仍然不能正确处理像2001年1月5日这样的日期。它首先满足yyyy MMM dd模式,而我最终得到的日期是00100624,这完全是任意的。 - Alagappan Ramu
根据Kayaman的建议,将setLenient设置为false可以帮助避免以上错误。 - Alagappan Ramu
1
但是你的“date_formats”列表不应该有MMM。在你的“possibility”列表(示例列表)中没有日期与之匹配。 - JHS
好的...但是,日期可能是“2013年1月5日”,那么模式“d MMMMM yyyy”能够解析它吗? - Alagappan Ramu

1

不要测试"yyyy-MM-dd",然后是"yyyy/MM/dd",再是"yyyy.MM.dd"(在许多国家使用),而是可以开始使用

token = token.replaceAll("-|\\.", "/");

这样可以将所有的点和破折号替换为“/”,并且您可以减少格式和尝试的数量。

0
Kayaman的答案是有效的,以下是代码片段,您可以轻松地测试它(直接从我的代码中复制粘贴):
static String[] date_formats = {
        "yyyy-MM-dd",
        "yyyy/MM/dd",
        "dd/MM/yyyy",
        "dd-MM-yyyy",
        "yyyy MMM dd",
        "yyyy dd MMM",
        "dd MMM yyyy",
        "dd MMM yyyy"};

static String[] dates = {
        "21/02/2012",
        "21-02-2012",
        "21-2-2012",
        "21 Feb 2012",
        "Feb 21 2012",//will not be parsed
        "21 februari 2012" //Dutch
};

@Test
public void test(){
    for(String date : dates) {
        parseDate(date);
        System.out.print("----------------");
    }
}

private void parseDate(String token){
    Locale dutch = new Locale("nl", "NL");
    for (String formatString : date_formats)
    {
        try
        {
            SimpleDateFormat format = new SimpleDateFormat(formatString, dutch);
            format.setLenient(false);
            Date mydate = format.parse(token);
            System.out.println(mydate.toString());
            break;
        }
        catch (ParseException e) {
            System.out.println("Next!");
        }
    }
}

0

添加日期格式"dd MMMMM YYYY",用于表示"5 January 2001"


0

这是你要找的吗?

String[] date_formats = {
                        "y-M-d",
                        "y/M/d", 
                        "d/M/y",
                        "d-M-y",
                        "y M d",
                        "y d M",
                        "d M y",
                        "d M",
                        "M d",
                        "d M y"};

String output_date = null;
for (String formatString : date_formats)
{
     try
     {    
         SimpleDateFormat sf = new SimpleDateFormat(formatString);  
         output_date = "5 January 2001"; 
         Date yourDate = sf.parse(output_date);
         break;
     }
     catch (ParseException e) {
         System.out.println("Next!");
     }
 }

0

您可以使用以下方法提取日期字符串:

String mydate = new SimpleDateFormat(formatString).format(new Date());

new Date() 会返回当前日期,你可以将它改为任何你想要的日期。

所以如果你像这样修改你的代码:

String[] date_formats = {
        "y-M-d",
        "y/M/d", 
        "d/M/y",
        "d-M-y",
        "y M d",
        "y d M",
        "d M y",
        "d M",
        "M d",
        "d M y"};

for (String formatString : date_formats)
    {
        String mydate = new SimpleDateFormat(formatString).format(new Date());
        System.out.println(mydate);
    }

你最终会得到这些:
2013-10-2
2013/10/2
2/10/2013
2-10-2013
2013 10 2
2013 2 10
2 10 2013
2 10
10 2
2 10 2013

0
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
    String dateInString = formatter.format(date);

    LOG.warn("date in String "+dateInString);

确保 MM 大写


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接