/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You 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.struts2.jasper.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 {

    private DateFormat df;
    private long lastSec = -1;
    private StringBuffer sb = new StringBuffer();
    private 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));
        }
    }
}
