1

我需要能够将日期的所有可能的字符串表示形式转换为 Date 对象。我知道这不是一项微不足道的任务,我主要寻求指导,因为我相信没有“单线”解决方案。

当前仅针对一种可能的输入类的示例:return new SimpleDateFormat("dd-MM-yyyy", Locale.ENGLISH).parse(input);

为了澄清我的问题,这里有一些可能的字符串输入:

  • 30-08-2011
  • 25.06.2011
  • 2011 年 6 月 15 日
  • 01-07-11
  • 19-9-2011

数据是由第三方提供的,所以我对此无能为力。我有一些关于检查分隔符是什么并据此选择正确格式的想法。

任何帮助表示赞赏。

问候。

编辑:我可以访问用户的区域设置,这样我实际上可以区分日期和月份部分。或者更确切地说,我可以访问日期的语言环境。

4

3 回答 3

1

第一个想法可能是检测非数字和非字母字符。这些字符在日期中分隔月、日和年。在您的示例中,这些是“-”、“”和“。”。

接下来,根据检测到的分隔符拆分字符串。

这给你: ["30","08","2011] 在第一种情况下。

然后我们可以检查年份是第一年还是最后一年。这可以通过检查位数来完成。如果 numDigits==4 那么你知道哪一年是年份。否则,您可以检查范围,是否不在 [1,31] 中,然后又是一年。如果他们都在 [1,31] 中,那么我看不出有明确的决定方式。(也许你更了解这一年的可能性?)

最后是中间的字符串。在那里您只需检查它是否包含字母字符或数字。

于 2013-07-16T13:52:23.790 回答
1

比我想象的更丑陋的代码。所以我会给它。拆分令牌,填充 3 个日期组件。仍然需要为给定的语言环境找到这些组件的顺序:Mdy、dMy。

public class DateIn {

    public static void main(String[] args) {
        String[] dates = {
            "30-08-2011",
            "25.06.2011",
            "15 Juni 2011",
            "01-07-11",
            "19-9-2011",
        };
        DateIn in = new DateIn();
        Locale locale = Locale.US;
        for (String date : dates) {
            try {
                Date d = in.read(date, locale);
                System.out.printf("%s -> %s%n", date,
                    new SimpleDateFormat("yyyy-MM-dd").format(d));
            } catch (IllegalArgumentException e) {
                System.out.println(e.getMessage());
            }
        }
    }

    private Date read(String date, Locale locale)
            throws IllegalArgumentException {
        final String[] ymdFormatters = { "y", "M", "d" };
        final int[] ymdGetters = { Calendar.YEAR, Calendar.MONTH,
            Calendar.DAY_OF_MONTH };
        String[] tokens = date.split("\\W+");
        final int Y = 0;
        final int M = 1;
        final int D = 2;
        int[] ymdValues = new int[3];
        for (String token : tokens) {
            if (token.matches("\\d+\\pL+")) { // 1st, 2nd, 3rd, 4th, 1e, ...
                token = token.replaceAll("\\pL+", "");
                ymdValues[D] = Integer.parseInt(token);
            } else if (token.matches("\\d+")) {
                int n = Integer.parseInt(token);
                if (n > 31) {
                    ymdValues[Y] = n;
                } else if (n > 12) {
                    ymdValues[D] = n;
                } else {
                    // Locale dependent order.
                    if (ymdValues[M] == 0) {
                        ymdValues[M] = n;
                    } else if (ymdValues[D] == 0) {
                        ymdValues[D] = n;
                    } else if (ymdValues[Y] == 0) {
                        ymdValues[Y] = n;
                    }
                }
            } else if (!token.isEmpty()) {
                for (int md = M; md <= D; ++md) {
                    String fmt = "";
                    for (int i = 0; i < 4; ++i) {
                        fmt += ymdFormatters[md];
                        SimpleDateFormat sdf = new SimpleDateFormat(fmt);
                        sdf.setLenient(true);
                        try {
                            Date dt = sdf.parse(token);
                            Calendar cal = Calendar.getInstance(locale);
                            cal.setTime(dt);
                            int n = cal.get(ymdGetters[md]);
                            if (md == M) {
                                ++n; // To 1-based
                            }
                            ymdValues[md] = n;
                            break;
                        } catch (ParseException e) {
                            //continue;
                        }
                    }
                }
            }
        }
        Calendar calendar = Calendar.getInstance(locale);
        for (int md = Y; md <= D; ++md) {
            int n = ymdValues[md];
            if (n == 0) {
                throw new IllegalArgumentException("Missing "
                    + ymdFormatters[md] + " part in " + date);
            }
            if (md == Y) {
                if (n < 100)
                    n += (calendar.get(Calendar.YEAR) / 100) * 100;
            } else if (md == M) {
                --n; // Calendar's month is 0-based.
            }
            calendar.set(ymdGetters[md], n);
        }
        return calendar.getTime();
    }
}
于 2013-07-16T14:42:59.283 回答
0

您可以尝试将字符串拆分为其组成部分(天、月、年)并单独解析它们。

前任:

String input = 30-08-2011;
if (input.indexOf("-") == -1)
return;
else    
   String day = index.substring(0, selected.indexOf("-"));

那么天,可以单独解析。然后对月份和年份重复该过程。然后您不必担心日期组件之间的格式。

于 2013-07-16T13:51:22.553 回答