/*
 * Copyright 1999,2004 The Apache Software Foundation.
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 *      http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.catalina.util;

import java.util.Date;

import java.text.DateFormat;
import java.text.FieldPosition;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;

/**
 * Fast date formatter that caches recently formatted date information
 * and uses it to avoid too-frequent calls to the underlying
 * formatter.  Note: breaks fieldPosition param of format(Date,
 * StringBuffer, FieldPosition).  If you care about the field
 * position, call the underlying DateFormat directly.
 *
 * @author Stan Bailes
 * @author Alex Chaffee
 **/
public class FastDateFormat extends DateFormat {
    DateFormat    df;
    long          lastSec = -1;
    StringBuffer  sb      = new StringBuffer();
    FieldPosition fp      = new FieldPosition(DateFormat.MILLISECOND_FIELD);

    public FastDateFormat(DateFormat df) {
        this.df = df;
    }

    public Date parse(String text, ParsePosition pos) {
        return df.parse(text, pos);
    }

    /**
     * Note: breaks functionality of fieldPosition param. Also:
     * there's a bug in SimpleDateFormat with "S" and "SS", use "SSS"
     * instead if you want a msec field.
     **/
    public StringBuffer format(Date date, StringBuffer toAppendTo,
                               FieldPosition fieldPosition) {
        long dt = date.getTime();
        long ds = dt / 1000;
        if (ds != lastSec) {
            sb.setLength(0);
            df.format(date, sb, fp);
            lastSec = ds;
        } else {
            // munge current msec into existing string
            int ms = (int)(dt % 1000);
            int pos = fp.getEndIndex();
            int begin = fp.getBeginIndex();
            if (pos > 0) {
                if (pos > begin)
                    sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
                ms /= 10;
                if (pos > begin)
                    sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
                ms /= 10;
                if (pos > begin)
                    sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
            }
        }
        toAppendTo.append(sb.toString());
        return toAppendTo;
    }

    public static void main(String[] args) {
        String format = "yyyy-MM-dd HH:mm:ss.SSS";
        if (args.length > 0)
            format = args[0];
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        FastDateFormat fdf = new FastDateFormat(sdf);
        Date d = new Date();

        d.setTime(1); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(20); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(500); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(543); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(999); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(1050); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(2543); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(12345); System.out.println(fdf.format(d) + "\t" + sdf.format(d));
        d.setTime(12340); System.out.println(fdf.format(d) + "\t" + sdf.format(d));

        final int reps = 100000;
        {
            long start = System.currentTimeMillis();
            for (int i = 0; i < reps; i++) {
                d.setTime(System.currentTimeMillis());
                fdf.format(d);
            }
            long elap = System.currentTimeMillis() - start;
            System.out.println("fast: " + elap + " elapsed");
            System.out.println(fdf.format(d));
        }
        {
            long start = System.currentTimeMillis();
            for (int i = 0; i < reps; i++) {
                d.setTime(System.currentTimeMillis());
                sdf.format(d);
            }
            long elap = System.currentTimeMillis() - start;
            System.out.println("slow: " + elap + " elapsed");
            System.out.println(sdf.format(d));
        }
    }
}
