docs: long parseParam(final String param) {
      if (param == null || param.isEmpty()) {
        throw new IllegalArgumentException(
            "Window parameter may not be null or empty");
      }
      final char[] chars = param.toCharArray();
      int idx = 0;
      for (int c = 1; c < chars.length; c++) {
        if (Character.isDigit(chars[c])) {
          idx++;
        } else {
          break;
        }
      }
      if (idx < 1) {
        throw new IllegalArgumentException("Invalid moving window parameter: " 
            + param);
      }
  
      try {
        final int time = Integer.parseInt(param.substring(1, idx + 1));
        final String unit = param.substring(idx + 1, param.length() - 1);
    
        // TODO(CL) - add a Graphite unit parser to DateTime for this kind of conversion
        if ("day".equals(unit) || "d".equals(unit)) {
          return TimeUnit.MILLISECONDS.convert(time, TimeUnit.DAYS);
        } else if ("hr".equals(unit) || "hour".equals(unit) || "h".equals(unit)) {
          return TimeUnit.MILLISECONDS.convert(time, TimeUnit.HOURS);
        } else if ("min".equals(unit) || "m".equals(unit)) {
          return TimeUnit.MILLISECONDS.convert(time, TimeUnit.MINUTES); 
        } else if ("sec".equals(unit) || "s".equals(unit)) {
          return TimeUnit.MILLISECONDS.convert(time, TimeUnit.SECONDS);
        } else {
          throw new IllegalArgumentException("Unknown time unit=" + unit 
              + " in window=" + param);
        }
      } catch (NumberFormatException nfe) {
        throw new IllegalArgumentException("Unable to parse moving window "
            + "parameter: " + param, nfe);
      }
    }