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

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

($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 {

  publicstatic final String CURRENT_YEAR ="$CURRENTYEAR";

  publicstatic final String CURRENT_MONTH ="$CURRENTMONTH";

  publicstatic final String CURRENT_WEEK ="$CURRENTWEEK";

  publicstatic final String CURRENT_DAY ="$CURRENTDAY";

  publicstatic final String CURRENT_HOUR ="$CURRENTHOUR";

  publicstatic final String CURRENT_MINUTE ="$CURRENTMINUTE";

  publicstatic final 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 staticfinal char YEAR ='Y';

  publicstatic final charMONTH = 'M';

  publicstatic final charDAY = 'D';

  publicstatic final charWEEK = 'W';

  publicstatic final charHOUR = 'H';

  publicstatic final charMINUTE = 'I';// MI

  publicstatic final charSECOND = 'S';


  publicstatic final charPLUS = '+';

  publicstatic final charMINUS = '-';


  protectedint expressionTypeIndex;


  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
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值