class TimeRangeChecker {

    public boolean evaluate(long timestamp) {
        if (match(whiteCache, timestamp)) {
            return true;
        }
        if (match(blackCache, timestamp)) {
            return false;
        }

        SimpleDateFormat fmt = new SimpleDateFormat(DATE_FORMAT);
        fmt.setTimeZone(tz);
        String date = fmt.format(timestamp);

        int[] p = parse(date);
        int[] rl = Arrays.copyOf(p, p.length);
        int[] ru = Arrays.copyOf(p, p.length);

        boolean match = match(p, lowerBound, upperBound);

        for(int j = 0; j != rl.length; ++j) {
            if (lowerBound[j] != -1) {
                rl[j] = lowerBound[j];
                ru[j] = upperBound[j];
            }
        }
        if (match) {
            // match
            long ldate = toDate(rl);
            long udate = toDate(ru);
            if (ldate == -1 || udate == -1) {
                // do not cache
                return true;
            }
            if (udate > ldate) {
                whiteCache = add(whiteCache, ldate, udate);
            }
            else {
                if (timestamp >= ldate && timestamp >= udate) {
                    udate = adjust(udate, 1);
                    whiteCache = add(whiteCache, ldate, udate);
                }
                else {
                    ldate = adjust(ldate, -1);
                    whiteCache = add(whiteCache, ldate, udate);
                }
            }
            return true;
        }
        else {
            // do not match
            long ldate = toDate(rl);
            long udate = toDate(ru);
            if (ldate == -1 || udate == -1) {
                // do not cache
                return false;
            }
            if (timestamp >= ldate && timestamp >= udate) {
                ldate = adjust(ldate, 1);
                blackCache = add(blackCache, udate, ldate);
            }
            else {
                udate = adjust(udate, -1);
                blackCache = add(blackCache, udate, ldate);
            }
            return false;
        }
    }

    public  TimeRangeChecker(String lower, String upper, TimeZone tz);

}