问题描述
我遇到过这种情况,我正在读取大约 130K 条记录,其中包含存储为字符串字段的日期.一些记录包含空格(空值),一些包含这样的字符串:'dd-MMM-yy',一些包含这个 'dd/MM/yyyy'.
I have this situation where I am reading about 130K records containing dates stored as String fields. Some records contain blanks (nulls), some contain strings like this: 'dd-MMM-yy' and some contain this 'dd/MM/yyyy'.
我写了一个这样的方法:
I have written a method like this:
public Date parsedate(String date){
if(date !== null){
try{
1. create a SimpleDateFormat object using 'dd-MMM-yy' as the pattern
2. parse the date
3. return the parsed date
}catch(ParseException e){
try{
1. create a SimpleDateFormat object using 'dd/MM/yyy' as the pattern
2. parse the date
3. return parsed date
}catch(ParseException e){
return null
}
}
}else{
return null
}
}
所以您可能已经发现了问题.我正在使用 try .. catch 作为我逻辑的一部分.最好是我可以事先确定字符串实际上包含某种格式的可解析日期,然后尝试解析它.
So you may have already spotted the problem. I am using the try .. catch as part of my logic. It would be better is I can determine before hand that the String actually contains a parseable date in some format then attempt to parse it.
那么,是否有一些 API 或库可以帮助解决这个问题?我不介意编写几个不同的 Parse 类来处理不同的格式,然后创建一个工厂来选择正确的 6 个,但是,我如何确定哪一个?
So, is there some API or library that can help with this? I do not mind writing several different Parse classes to handle the different formats and then creating a factory to select the correct6 one, but, how do I determine which one?
谢谢.
推荐答案
参见 Java 中的延迟错误处理 概述了如何使用 Option
类型消除 try/catch 块.
See Lazy Error Handling in Java for an overview of how to eliminate try/catch blocks using an Option
type.
Functional Java 是您的朋友.
本质上,你想要做的是将日期解析包装在一个不抛出任何东西的函数中,但在其返回类型中指示解析是否成功.例如:
In essence, what you want to do is to wrap the date parsing in a function that doesn't throw anything, but indicates in its return type whether parsing was successful or not. For example:
import fj.F; import fj.F2;
import fj.data.Option;
import java.text.SimpleDateFormat;
import java.text.ParseException;
import static fj.Function.curry;
import static fj.Option.some;
import static fj.Option.none;
...
F<String, F<String, Option<Date>>> parseDate =
curry(new F2<String, String, Option<Date>>() {
public Option<Date> f(String pattern, String s) {
try {
return some(new SimpleDateFormat(pattern).parse(s));
}
catch (ParseException e) {
return none();
}
}
});
好的,现在您有了一个不抛出任何内容的可重用日期解析器,但通过返回 Option.None
类型的值来指示失败.使用方法如下:
OK, now you've a reusable date parser that doesn't throw anything, but indicates failure by returning a value of type Option.None
. Here's how you use it:
import fj.data.List;
import static fj.data.Stream.stream;
import static fj.data.Option.isSome_;
....
public Option<Date> parseWithPatterns(String s, Stream<String> patterns) {
return stream(s).apply(patterns.map(parseDate)).find(isSome_());
}
这将为您提供使用匹配的第一个模式解析的日期,或 Option.None 类型的值,这是类型安全的,而 null 不是.
That will give you the date parsed with the first pattern that matches, or a value of type Option.None, which is type-safe whereas null isn't.
如果您想知道 Stream
是什么...这是一个懒惰的列表.这可确保您在第一个成功模式后忽略模式.无需做太多工作.
If you're wondering what Stream
is... it's a lazy list. This ensures that you ignore patterns after the first successful one. No need to do too much work.
像这样调用你的函数:
for (Date d: parseWithPatterns(someString, stream("dd/MM/yyyy", "dd-MM-yyyy")) {
// Do something with the date here.
}
或者...
Option<Date> d = parseWithPatterns(someString,
stream("dd/MM/yyyy", "dd-MM-yyyy"));
if (d.isNone()) {
// Handle the case where neither pattern matches.
}
else {
// Do something with d.some()
}
这篇关于在解析之前确定字符串是否为有效日期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!