Java 不指定格式的自动日期/时间分析器

Java 不指定格式的自动日期/时间分析器,java,datetime,date-parsing,Java,Datetime,Date Parsing,我正在搜索一个java库,它可以在不指定格式的情况下将字符串解析为POJO。我已经研究过了。还有其他图书馆做类似的事情吗 DateTime-DateTime=DateTimeParser.parse(“21/02/13”); //如果不清楚,请使用传递的文化信息 DateTime DateTime=DateTimeParser.parse(“01/02/13”,新语言环境(“en-us”); //也应适用于时区 DateTime DateTime=DateTimeParser.parse(“20

我正在搜索一个java库,它可以在不指定格式的情况下将字符串解析为POJO。我已经研究过了。还有其他图书馆做类似的事情吗

DateTime-DateTime=DateTimeParser.parse(“21/02/13”);
//如果不清楚,请使用传递的文化信息
DateTime DateTime=DateTimeParser.parse(“01/02/13”,新语言环境(“en-us”);
//也应适用于时区
DateTime DateTime=DateTimeParser.parse(“2011/12/13T14:15:16+01:00”);
我发现以下链接与同一问题有关,但不是非常有用的答案。Joda和JChronic都不是我想要的。如果我错了,请纠正我

更新:

我之所以说Joda不能解决我的问题,是因为Joda希望字符串以ISO8601格式或您指定的任何格式(如“yyyyMMdd”)进行解析。我将无法硬编码这种格式,因为我需要处理几种格式


我有一个解决方案,可以消除美国或欧洲日期格式的歧义,即mm/dd/yy或dd/mm/yy。假设我可以访问日期的时区,我可以确定它是美国格式还是欧洲格式吗?有人能告诉我怎么做吗?谷歌搜索了一下,但什么也没找到

问题在于有些格式无法正确猜测

一个简单的例子是
01/02/2013
。这是二月一日还是一月二日?甚至更糟:
01/02/09

两种格式都存在。(谢谢你,英国和美国!)

因此,任何格式猜测者都必须依靠运气来猜测这些格式,否则就会故意失败

python模块
dateutil.parser
可以作为尽力而为的解析器的示例。很抱歉,我不知道java等价物。但你可能想看看

它实际上有参数
dayfirst
yearfirst

还有一个perl模块:


您可以使用该模块中的优先级列表。盲目地尝试一些模式并不快(优化的lexer会快得多),但它可能对你来说已经足够好了,除非你正在猜测数百万条记录的格式。

对此没有神奇的解决方案。请记住,日期/时间格式也可能取决于您的区域设置

实际上,你能做的最好的事情就是定义一个格式列表,然后一个接一个地“尝试”它们,直到你找到一个(或没有)适合的

private static final FORMAT_1 = "MM/dd/yyyy'T'HH:mm:ss.SSS"
private static final FORMAT_2 = "MM/dd/yyyy'T'HH:mm:ss"
private static final FORMAT_3 = "MM/dd/yyyy"
在java中使用日期/时间对象时,请记住考虑线程安全。我有一个类在做这类事情,名为“ThreadSafeDateTimeFormatter”


祝你好运

我找到了问题的答案。我用过这个特别的图书馆。这说明了如何在不指定任何格式的情况下格式化日期+时间字符串。但是,为了使库正常工作,您必须指定日期顺序,如日期后接月份或月后接天。

由于我没有找到适合我的情况的简便解决方案,因此我编写了一个简单的静态实用程序方法来帮助我。如果添加了更多的格式,在集合中包装格式并对其进行迭代可以使事情变得更容易

public static Date returnDateFromDateString(String propValue) throws Exception {

    SimpleDateFormat sdfFormat1 = new SimpleDateFormat(IDateFConstants.DATE_STRING_FORMAT_1);
    SimpleDateFormat sdfFormat2 = new SimpleDateFormat(IDateFConstants.DATE_STRING_FORMAT_2);
    SimpleDateFormat sdfISO8601 = new SimpleDateFormat(IDateFConstants.DATE_STRING_ISO_8601);

    try {
        return sdfFormat1.parse(propValue);
    } catch (ParseException e) { }

    try {
        return sdfFormat2.parse(propValue);
    } catch (ParseException e) { }

    try {
        return sdfISO8601.parse(propValue);
    } catch (ParseException e) { }

    throw new Exception(IDateFConstants.DATE_FORMAT_ERROR);
}
其中,
IDATEF常量
看起来像

public interface IDateFConstants {

public static final String DATE_STRING_ISO_8601 = "yyyy-MM-dd'T'HH:mm:ss";
public static final String DATE_STRING_FORMAT_1 = "dd.MM.yyyy";
public static final String DATE_STRING_FORMAT_2 = "dd.MM.yyyy HH:mm:ss";

public static final String DATE_FORMAT_ERROR = "Date string wasn't" + 
                                            + "formatted in known formats";

}

您至少需要有一个有序的候选模式列表。一旦有了它,就有了一个
parseDate(String-dateString,String[]patterns)
方法,让您可以轻松地尝试日期字符串上的模式列表,并通过第一个匹配的模式对其进行解析:

public static Date parseDate(String str,
                         String[] parsePatterns)
                  throws ParseException
Parses a string representing a date by trying a variety of different parsers.
解析将依次尝试每个解析模式。解析仅被视为 如果它解析整个输入字符串,则成功。如果没有解析 模式匹配时,将引发ParseException

解析器将对解析的日期宽大处理


此日期/时间解析器支持20多种日期格式,用户可以将日期格式设置为输入配置。查看完整的文档,它比其他日期时间库做得更多

Github链接:。 由ZOHO ZIA团队开发

Hawking解析器是一种基于Java的NLP解析器,用于解析日期和时间信息。最流行的解析器,如Heidel Time、SuTime和Natty Date Time解析器都是基于规则的。因此,他们往往难以解析日期/时间信息,需要考虑上下文、时态、多值等更复杂的因素

考虑到这一点,Hawking解析器被设计用于解决许多这些挑战,并且与其他可用的日期/时间解析器相比具有许多明显的优势

它是GPLv3下的一个开源库,也是最好的一个。要了解为什么这是最好的,请查看此博客,其中详细说明:


附言:我是这个项目的开发人员之一

你希望第一个版本在2013年5月6日的
上做什么?无论你选择什么,你都会对地球上相当大的一部分人来说是错误的。你看了Joda Time了吗?如果第一行有歧义,请使用默认的文化信息,除非在第二行代码中指定了一个,如果第一行有歧义,则可能重复(请参考原始问题中的代码),使用默认文化信息,除非在第二个代码行中指定了文化信息。我能从任何图书馆得到这种情报吗?我注意到你已经写了几个链接到你网站的答案。到目前为止,它们似乎都与这些问题相关,并且只有少数几个答案,所以这很好。但我要提醒你,即使你披露了与链接资源的联系,继续重复和/或不必要地推广你的内容也可能被视为垃圾邮件。请参阅了解更多信息。感谢您让我知道。在发布答案之前,请记住这一点
        public static String detectDateFormat(String inputDate, String requiredFormat) {
        String tempDate = inputDate.replace("/", "").replace("-", "").replace(" ", "");
        String dateFormat;

        if (tempDate.matches("([0-12]{2})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMddyyyy";
        } else if (tempDate.matches("([0-31]{2})([0-12]{2})([0-9]{4})")) {
            dateFormat = "ddMMyyyy";
        } else if (tempDate.matches("([0-9]{4})([0-12]{2})([0-31]{2})")) {
            dateFormat = "yyyyMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([0-12]{2})")) {
            dateFormat = "yyyyddMM";
        } else if (tempDate.matches("([0-31]{2})([a-z]{3})([0-9]{4})")) {
            dateFormat = "ddMMMyyyy";
        } else if (tempDate.matches("([a-z]{3})([0-31]{2})([0-9]{4})")) {
            dateFormat = "MMMddyyyy";
        } else if (tempDate.matches("([0-9]{4})([a-z]{3})([0-31]{2})")) {
            dateFormat = "yyyyMMMdd";
        } else if (tempDate.matches("([0-9]{4})([0-31]{2})([a-z]{3})")) {
            dateFormat = "yyyyddMMM";
        } else {
//add your required regex
            return "";
        }
        try {
            String formattedDate = new SimpleDateFormat(requiredFormat, Locale.ENGLISH).format(new SimpleDateFormat(dateFormat).parse(tempDate));

            return formattedDate;
        } catch (Exception e) {

            return "";
        }

    }