时间定位表达式-用于时间的加、减调整

来源:互联网 发布:电脑椅推荐 知乎 编辑:程序博客网 时间:2024/06/15 19:21

在笔者开发的应用中,经常会遇到用户对数据有按照时间进行查询或监视的需求。用户对此类需求往往是希望可以输入一个已当前时间为准,向前回溯或向后延展一定时间的一个时间段。时间段可以是一天、一周、一个月,也可以是十天、一百天、十周等。为可以灵活满足此类需求,笔者写了一个专门做时间定位运算的表达式--“时间定位表达式”。其具体格式如下:

($Now|$CurrentYear|…) [(+|-) num(y|m|w|d|h|mi|s)]+

时间定位表达式分为两个部分,“($Now|$CurrentYear|…)”部分称为锚表达式,用于标定时间计算的起始点;“[(+|-) num(y|m|w|d|h|mi|s)]+”部分称为调整表达式,用于根据起始点调整计算时间。如:$Now+3m+5h -40mi+20s。表示以当前时间为基础,在当前月的基础上在加上3个月,在当前小时的基础上加上5小时,在当前分钟的基础上减去40分钟,在当前秒的基础上加上20秒。若当前时间为2013-9-11 14:35:45,计算后的时间为:2014-1-1118:56:05。

锚表达式的定位标记除$Now外,还有$CurrentYear,$CurrentMonth,$CurrentWeek,$CurrentDay,$CurrentHour,$CurrentMinute。若当前时间为2013-9-2214:23:38,则$Now的值为2013-9-22 14:23:38;$CurrentYear的值为2013-1-1 00:00:00,即$CurrentYear定位的时间为某年的1月1日零时;$CurrentMonth的值为2013-9-100:00:00,即$CurrentMonth定位的时间为某年某月的第1天的零时;$CurrentWeek的值为2013-9-16 00:00:00;$CurrentDay的值为2013-9-22 00:00:00,即$CurrentDay定位的时间为该天的零时;$CurrentHour的值为2013-9-2214:00:00,即$CurrentHour定位的时间为该时刻的整点;$CurrentMinute的值为2013-9-2214:23:00,即$CurrentMinute定位的时间为该分钟的整点时刻。

调整表达式的调整幅度后缀。y后缀表示年,m后缀表示月,w后缀表示周,d后缀表示天,h后缀表示小时,mi后缀表示分钟,s后缀表示秒。表达式支持“+”和“-”两种运算操作。支持对某个时间单位的连加连减操作,如:$Now-12d+5d等。

另外,该表达式是大小写不敏感的,其实现代码如下,由于逻辑简单就不解释了,大家自己看吧:

public class TposExpression implements Serializable {

  publicstaticfinal String CURRENT_YEAR ="$CURRENTYEAR";

  publicstaticfinal String CURRENT_MONTH ="$CURRENTMONTH";

  publicstaticfinal String CURRENT_WEEK ="$CURRENTWEEK";

  publicstaticfinal String CURRENT_DAY ="$CURRENTDAY";

  publicstaticfinal String CURRENT_HOUR ="$CURRENTHOUR";

  publicstaticfinal String CURRENT_MINUTE ="$CURRENTMINUTE";

  publicstaticfinal String CURRENT_POSITION ="$NOW";


  public static final String[] expressionTypes =new String[] {

      CURRENT_YEAR,CURRENT_MONTH,CURRENT_WEEK, CURRENT_DAY, CURRENT_HOUR,

      CURRENT_MINUTE,CURRENT_POSITION

  };

  public staticfinalchar YEAR ='Y';

  publicstaticfinal charMONTH ='M';

  publicstaticfinal charDAY ='D';

  publicstaticfinal charWEEK ='W';

  publicstaticfinal charHOUR ='H';

  publicstaticfinal charMINUTE ='I';// MI

  publicstaticfinal charSECOND ='S';


  publicstaticfinal charPLUS ='+';

  publicstaticfinal charMINUS ='-';


  protectedintexpressionTypeIndex;


  protected StringanchorExpression;


  protected StringadjustExpression;


  public TposExpression(String expression) {

    Validate.notEmpty(expression, "expression is empty!");

    expression = expression.trim();

    expressionTypeIndex = checkExpression(expression);

    splitExression(expression);

  }

  protected int checkExpression(String expression) {

    expression = expression.toUpperCase();

    for (int i = 0; i <expressionTypes.length; i++) {

      if (expression.startsWith(expressionTypes[i])) {

        return i;

      }

    }

    throw new IllegalArgumentException(

        "Invalid expression! Should be started with '$CurrentYear',"

            + "'$CurrentMonth','$CurrentWeek','$CurrentDay','$CurrentHour','$CurrentMinute','$Now' ");

  }


  protected void splitExression(String expression) {

    anchorExpression =expressionTypes[expressionTypeIndex];

    adjustExpression = expression

        .substring(expressionTypes[expressionTypeIndex].length());

    adjustExpression =adjustExpression.toUpperCase();

  }


  public Date getDate() {

    Calendar calendar = Calendar.getInstance();

    anchor(calendar, expressionTypeIndex);

    position(calendar, adjustExpression); // offset

    return calendar.getTime();

  }

  //静态方法,指定起始时间和调整表达式,直接定位时间。该起始时间可以是锚表达式支持不了的任意时间

  public static Date position(Date date, String adjustExpression) {

    Validate.notNull(date, "date is null!");

    Validate.notEmpty(adjustExpression,"adjustExpression is empty!");

    adjustExpression = adjustExpression.toUpperCase();

    Calendar calendar = Calendar.getInstance();

    calendar.setTime(date);

    position(calendar, adjustExpression);

    return calendar.getTime();

  }


  protected static void position(Calendar calendar, String expression) {

    char operate =' ', flag =' ';

    int num = -1;

    for (int i = 0; i < expression.length(); i++) {

      char ch = expression.charAt(i);

      if (ch ==' ')

        continue;

      if (ch ==PLUS || ch ==MINUS) {

        operate = ch;

      } else if (Character.isDigit(ch)) {

        int j = i + 1;

        for (; j < expression.length(); j++) {

          ch = expression.charAt(j);

          if (!Character.isDigit(ch)) {

            break;

          }

        }

        if (j == expression.length()) {

          thrownew IllegalArgumentException("Invalid expression");

        }

        String sub = expression.substring(i, j);

        num = Integer.valueOf(sub).intValue();

        i = j - 1;

      } else if (ch == YEAR || ch == MONTH || ch ==DAY || ch ==WEEK

          || ch == HOUR || ch ==SECOND) {

        if (ch ==MONTH) {

          if (i + 1 < expression.length() && expression.charAt(i + 1) ==MINUTE) {

            ch = MINUTE;

            i++;

          }

        }

        flag = ch;

        calc(calendar, operate, flag, num);

        operate = ' ';

        flag = ' ';

        num = -1;

      }

    }

  }


  protected static void calc(Calendar calendar, char operate, char flag, int num) {

    if (operate ==PLUS) {

      plus(calendar, flag, num);

    } else if (operate == MINUS) {

      minus(calendar, flag, num);

    } else {

      throw new IllegalArgumentException("Invalid operate!");

    }

  }


  protected static void plus(Calendar calendar, char flag, int num) {

    switch (flag) {

      case YEAR:

        int year = calendar.get(Calendar.YEAR);

        year += num;

        calendar.set(Calendar.YEAR, year);

        break;

      case MONTH:

        int month = calendar.get(Calendar.MONTH);

        month += num;

        calendar.set(Calendar.MONTH, month);

        break;

      case WEEK:

        num *= 7;

      case DAY:

        int day = calendar.get(Calendar.DAY_OF_YEAR);

        day += num;

        calendar.set(Calendar.DAY_OF_YEAR, day);

        break;

      case HOUR:

        int hour = calendar.get(Calendar.HOUR_OF_DAY);

        hour += num;

        calendar.set(Calendar.HOUR_OF_DAY, hour);

        break;

      case MINUTE:

        int minute = calendar.get(Calendar.MINUTE);

        minute += num;

        calendar.set(Calendar.MINUTE, minute);

        break;

      case SECOND:

        int second = calendar.get(Calendar.SECOND);

        second += num;

        calendar.set(Calendar.SECOND, second);

        break;

      default:

        throw new IllegalArgumentException("Invalid flag!");

    }

  }


  protected static void minus(Calendar calendar, char flag, int num) {

    switch (flag) {

      case YEAR:

        int year = calendar.get(Calendar.YEAR);

        year -= num;

        calendar.set(Calendar.YEAR, year);

        break;

      case MONTH:

        int month = calendar.get(Calendar.MONTH);

        month -= num;

        calendar.set(Calendar.MONTH, month);

        break;

      case WEEK:

        num *= 7;

      case DAY:

        int day = calendar.get(Calendar.DAY_OF_YEAR);

        day -= num;

        calendar.set(Calendar.DAY_OF_YEAR, day);

        break;

      case HOUR:

        int hour = calendar.get(Calendar.HOUR_OF_DAY);

        hour -= num;

        calendar.set(Calendar.HOUR_OF_DAY, hour);

        break;

      case MINUTE:

        int minute = calendar.get(Calendar.MINUTE);

        minute -= num;

        calendar.set(Calendar.MINUTE, minute);

        break;

      case SECOND:

        int second = calendar.get(Calendar.SECOND);

        second -= num;

        calendar.set(Calendar.SECOND, second);

        break;

      default:

        throw new IllegalArgumentException("Invalid flag!");

    }

  }


  protected static void anchor(Calendar calendar, int expressionTypeIndex) {

    switch (expressionTypeIndex) {

      case 0:

        calendar.set(Calendar.MONTH, 0);

      case 1:

        calendar.set(Calendar.DAY_OF_MONTH, 1);

      case 3:

        calendar.set(Calendar.HOUR_OF_DAY, 0);

      case 4:

        calendar.set(Calendar.MINUTE, 0);

      case 5:

        calendar.set(Calendar.SECOND, 0);

        calendar.set(Calendar.MILLISECOND, 0);

        break;

      case 2:

        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);

        if (dayOfWeek == 1) {

          calendar.set(Calendar.DAY_OF_YEAR,

              calendar.get(Calendar.DAY_OF_YEAR) - 7);

        }

        calendar.set(Calendar.DAY_OF_WEEK, 2);// Monday

        calendar.set(Calendar.HOUR_OF_DAY, 0);

        calendar.set(Calendar.MINUTE, 0);

        calendar.set(Calendar.SECOND, 0);

        calendar.set(Calendar.MILLISECOND, 0);

        break;

    }

  }


  public String getAnchorExpression() {

    returnanchorExpression;

  }


  public String getAdjustExpression() {

    returnadjustExpression;

  }


}



 




0 0
原创粉丝点击