Java字符串解析和评估

时间:2011-09-15 10:29:56

标签: java string parsing

所有

我正在处理或重写我之前写过的一些代码。该代码的目标是基于以下格式的字符串计算日期和时间:

  • 一天开始+ 2HOUR + 1天-2分钟
  • NOW + 20Day
  • MonthStart + 1个月

哪一天(当地时间)开始,例如2011-09-15 00:00:00 BST(2011-09-15 23:00 GMT)然后加2小时,加1天,减去2分钟。

实现是用Java编写的,原始算法非常基础。它遍历字符串中的每个字符并附加到缓冲区。然后检查缓冲区以查看它是否以我正在查找的字符串结束(日期说明符,例如MINUTE,HOUR,DAYSTART等)然后提取数字并添加到ArrayList,其中DateOffset是一个带有int和String的简单类这是日期说明者。以下是一些示例代码:

// hard coded for sample
String s = "DayStart+2Hour+1Day-2Minutes";

StringBuilder sbBuffer = new StringBuilder();
String buffer;

// iterate through date string
for (char c : s.toCharArray()) {
    sbBuffer.append(c);
    buffer = sbBuffer.toString();

    // check to see the end of the buffer string is what we expect
    if (buffer.endsWith("DAYSTART")) {
        offsets.add(new DateOffset(0, "DAYSTART"));
        sbBuffer = new StringBuilder();
    } else if (buffer.endsWith("DAY") && buffer.length() > 3) {
        String numberStringPart = buffer.substring(0, buffer.length() - 3);
        numberStringPart = numberStringPart.replaceAll("[+]", "").trim();  // need as parseInt does not like the +.

        offsets.add(new DateOffset(Integer.parseInt(numberStringPart), "DAY"));
        sbBuffer = new StringBuilder();
    } ... and so on ...
    else {
    }
}

解析字符串后,我遍历ArrayList来计算我的日期时间。

虽然我们没有遇到任何问题,但上述问题可能效率不高。它也不会发现任何错误,因此您可以输入DayStart + 2GKGKER。

我只想提出一些关于用什么来重写它的新鲜而全新的想法。我做了一点正则表达式,但不太确定这是否是最好的路线。

有什么想法吗?

谢谢,

Andez

4 个答案:

答案 0 :(得分:3)

为表达式定义语法。看一下ANTLR框架,帮助您构建语法并处理表达式。

答案 1 :(得分:1)

如果您正在进行快速实验,有时候一个识字的API与即时编辑相结合是一种简单的方法。

因此,您的示例可能看起来像(给定适当的静态导入)

daystart().plus()
    .hours(2).plus()
    .days(1).minutes(2)

或甚至(以毫秒为基本单位)

daystart() + hours(2) + days(1) - minutes(2)

答案 2 :(得分:1)

哇哇,真有趣!谢谢! : - )

public class DateExpressions {
    private Map<String, Date> dateVariables;
    private Map<String, Integer> temporalUnits;
    private Map<Character, Integer> temporalOperations;

    public static DateExpressions createInstance() {
        DateExpressions de = new DateExpressions();
        Calendar c = Calendar.getInstance();
        de.setVariable("NOW", c.getTime());

        c.set(Calendar.HOUR_OF_DAY, 0);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);
        c.set(Calendar.MILLISECOND, 0);
        de.setVariable("DayStart", c.getTime());

        c.set(Calendar.DAY_OF_MONTH, 1);
        de.setVariable("MonthStart", c.getTime());

        return de;
    }

    public DateExpressions() {
        this.dateVariables = new HashMap<String, Date>();
        this.temporalUnits = new HashMap<String, Integer>();
        this.temporalUnits.put("Second", Calendar.SECOND);
        this.temporalUnits.put("Minute", Calendar.MINUTE);
        this.temporalUnits.put("Hour", Calendar.HOUR_OF_DAY);
        this.temporalUnits.put("Day", Calendar.DATE);
        this.temporalUnits.put("Month", Calendar.MONTH);
        this.temporalUnits.put("Year", Calendar.YEAR);

        this.temporalOperations = new HashMap<Character, Integer>();
        this.temporalOperations.put('+', 1);
        this.temporalOperations.put('-', -1);
    }

    public void setVariable(String key, Date value) {
        this.dateVariables.put(key, value);
    }

    public Date parseExpression(String expr) throws IOException {
        StringReader sr = new StringReader(expr);
        String s;
        int n;
        char c;

        int offset;
        int unit;
        int op = 1;

        Calendar base = null;
        StringBuilder sb1 = new StringBuilder();
        StringBuilder sb2 = new StringBuilder();
        while ((n = sr.read()) != -1) {
            c = (char) n;

            if (base == null && temporalOperations.containsKey(c)) {
                s = sb2.toString();
                if (!dateVariables.containsKey(s)) {
                    throw new IOException("Unknown variable '" + s + "' used");
                }

                base = Calendar.getInstance();
                base.setTime(dateVariables.get(sb2.toString()));
                op = temporalOperations.get(c);

                sb1.setLength(0);
                sb2.setLength(0);
            } else if (temporalOperations.containsKey(c)) {
                if (!temporalUnits.containsKey(sb2.toString())) {
                    throw new IOException(
                            "Parse error: unknown temporal unit used '"
                                    + sb2.toString() + "'");
                }

                offset = Integer.parseInt(sb1.toString());
                unit = temporalUnits.get(sb2.toString());

                base.add(unit, op * offset);

                op = temporalOperations.get(c);
                sb1.setLength(0);
                sb2.setLength(0);
            } else if (Character.isDigit(c)) {
                sb1.append(c);
            } else {
                sb2.append(c);
            }
        }

        if (!temporalUnits.containsKey(sb2.toString())) {
            throw new IOException("Parse error: unknown temporal unit used '"
                    + sb2.toString() + "'");
        }

        offset = Integer.parseInt(sb1.toString());
        unit = temporalUnits.get(sb2.toString());

        base.add(unit, op * offset);

        return base.getTime();
    }

    public static void main(String[] args) throws IOException {
        DateExpressions de = DateExpressions.createInstance();
        System.out.println(de.parseExpression("DayStart+2Hour+1Day-2Minute"));
        System.out.println(de.parseExpression("NOW+20Day"));
        System.out.println(de.parseExpression("MonthStart+1Month"));
    }
}

答案 3 :(得分:0)

正则表达式似乎是这种情况的最佳选择。虽然,我很困惑你为什么要以这种方式解释字符串,而不是使用复杂的API。