java 不指定格式的自动日期/时间解析器
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/15010210/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Automatic Date/Time parser without specifying format
提问by saravanan07
I am searching for a java library that can parse a string into a POJO without specifying the format. I have researched POjava. Is there anyother library which does similar thing?
我正在寻找一个可以在不指定格式的情况下将字符串解析为 POJO 的 Java 库。我研究过POjava。有没有其他图书馆做类似的事情?
DateTime dateTime = DateTimeParser.parse("21/02/13");
//If unclear use the cultural information passed
DateTime dateTime = DateTimeParser.parse("01/02/13", new Locale("en-us"));
//Should also work with time zones
DateTime dateTime = DateTimeParser.parse("2011/12/13T14:15:16+01:00");
I found the following links with the same problem Intelligent date / time parser for Java, but not very useful answers. Neither Joda or JChronic does what I wanted. Correct me if I am wrong.
我发现以下链接具有相同的问题Intelligent date / time parser for Java,但不是很有用的答案。Joda 或 JChronic 都没有做我想要的。如果我错了,请纠正我。
Update:
更新:
The reason I say Joda does not solve my purpose is, Joda expects the string to be parsed in ISO8601 format or any format you specify like "yyyyMMdd". I will not be able to hardcode this format as I need to handle several formats.
我说 Joda 没有解决我的目的的原因是,Joda 希望以 ISO8601 格式或您指定的任何格式(如“yyyyMMdd”)解析字符串。我将无法对此格式进行硬编码,因为我需要处理多种格式。
I have a hack around solution for eliminating the ambiguity with respect to American or European date formats, i.e. mm/dd/yy or dd/mm/yy. Assuming I have access to timezone of the date, can I determine if it is American or European format? Can someone tell me way to do this? Googled but found nothing.
我有一个解决方案来消除美国或欧洲日期格式的歧义,即 mm/dd/yy 或 dd/mm/yy。假设我可以访问日期的时区,我可以确定它是美国格式还是欧洲格式?有人可以告诉我如何做到这一点吗?谷歌搜索,但一无所获。
采纳答案by saravanan07
I found the answer to my problem. I used this particular library POjava. This pageexplains how you can format the date+time string without specifying any format. However, for the library to work properly, you got to specify the date ordering like Day followed by Month or Month followed by Day.
我找到了我的问题的答案。我使用了这个特殊的库POjava。此页面介绍了如何格式化日期+时间字符串不指定任何格式。但是,要使库正常工作,您必须指定日期顺序,例如日后接月或月后接日。
回答by Has QUIT--Anony-Mousse
The problem is that there are some formats that cannotbe guessed right.
问题是有些格式无法猜对。
A simple example is 01/02/2013
. Is this february 1st or january 2nd? Or even worse: 01/02/09
?
一个简单的例子是01/02/2013
。这是2月1日还是1月2日?或者更糟:01/02/09
?
Bothformats exist. (Thank you, UK and US!)
两种格式都存在。(谢谢英国和美国!)
So any format guesser will have to rely on luck for these formats, or fail deliberately for these.
因此,任何格式猜测者都将不得不依赖这些格式的运气,或者故意为这些格式失败。
The python module dateutil.parser
can serve as an example of a best effort parser. Sorry that I don't know a java equivalent. But you might want to look at Joda Time
python 模块dateutil.parser
可以作为尽力而为解析器的示例。抱歉,我不知道 Java 等价物。但你可能想看看Joda Time
http://labix.org/python-dateutil#head-b95ce2094d189a89f80f5ae52a05b4ab7b41af47
http://labix.org/python-dateutil#head-b95ce2094d189a89f80f5ae52a05b4ab7b41af47
it actually has parameters dayfirst
and yearfirst
.
它实际上有参数dayfirst
和yearfirst
。
Then there is a perl module:
然后是一个 perl 模块:
https://metacpan.org/pod/Time::ParseDate
https://metacpan.org/pod/Time::ParseDate
You might be able to use the precedence list from that module. It's not very fast to blindly try a number of patterns (an optimized lexer will be way faster), but it may be good enough for you, unless you are guessing the format of millions of records.
您也许可以使用该模块中的优先级列表。盲目尝试多种模式并不是很快(优化的词法分析器会更快),但它可能对你来说已经足够了,除非你在猜测数百万条记录的格式。
回答by Miki
Since I didn't find handy solution for my situation I wrote a simple static utility method that helped me. Wrapping formats in collection and iterating over it could make things easier if many more formats are added.
由于我没有找到适合我的情况的方便解决方案,因此我编写了一个简单的静态实用程序方法来帮助我。如果添加更多格式,将格式包装在集合中并对其进行迭代可以使事情变得更容易。
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);
}
where IDateFConstants
looks like
哪里IDateFConstants
看起来像
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";
}
回答by Sanchay
You need to at least have an ordered list of pattern candidates. Once you have that, Apache DateUtilshas a parseDate(String dateString, String[] patterns)
method that lets you easily try out a list of patterns on your date string, and parse it by the first one that matches:
您至少需要有一个有序的模式候选列表。一旦你有了它,Apache DateUtils有一个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.
The parse will try each parse pattern in turn. A parse is only deemed successful if it parses the whole of the input string. If no parse patterns match, a ParseException is thrown.
The parser will be lenient toward the parsed date.
解析将依次尝试每个解析模式。只有解析了整个输入字符串,解析才被认为是成功的。如果没有匹配的解析模式,则抛出 ParseException。
解析器将对解析日期宽容。
回答by Suheb Rafique
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 "";
}
}
回答by vikingsteve
There is no magic solution to this. Remember date/time formats can also depend on your locale.
对此没有神奇的解决方案。请记住,日期/时间格式也可能取决于您的语言环境。
Realistically the best you can do is define a list of formats, and "try" them one by one until you find one (or none) that fit.
实际上,你能做的最好的事情就是定义一个格式列表,然后一个一个地“尝试”它们,直到找到一个(或一个)合适的。
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"
Remember to think about thread safety when working with date/time objects in java. I have a class doing this sort of stuff named "ThreadSafeDateTimeFormatter".
在 Java 中处理日期/时间对象时,请记住要考虑线程安全。我有一个班级在做这种名为“ThreadSafeDateTimeFormatter”的事情。
Good luck!
祝你好运!