001: /*
002: * ====================================================================
003: *
004: * The Apache Software License, Version 1.1
005: *
006: * Copyright (c) 1999 The Apache Software Foundation. All rights
007: * reserved.
008: *
009: * Redistribution and use in source and binary forms, with or without
010: * modification, are permitted provided that the following conditions
011: * are met:
012: *
013: * 1. Redistributions of source code must retain the above copyright
014: * notice, this list of conditions and the following disclaimer.
015: *
016: * 2. Redistributions in binary form must reproduce the above copyright
017: * notice, this list of conditions and the following disclaimer in
018: * the documentation and/or other materials provided with the
019: * distribution.
020: *
021: * 3. The end-user documentation included with the redistribution, if
022: * any, must include the following acknowlegement:
023: * "This product includes software developed by the
024: * Apache Software Foundation (http://www.apache.org/)."
025: * Alternately, this acknowlegement may appear in the software itself,
026: * if and wherever such third-party acknowlegements normally appear.
027: *
028: * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
029: * Foundation" must not be used to endorse or promote products derived
030: * from this software without prior written permission. For written
031: * permission, please contact apache@apache.org.
032: *
033: * 5. Products derived from this software may not be called "Apache"
034: * nor may "Apache" appear in their names without prior written
035: * permission of the Apache Group.
036: *
037: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
038: * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
039: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
040: * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
041: * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
042: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
043: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
044: * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
045: * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
046: * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
047: * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
048: * SUCH DAMAGE.
049: * ====================================================================
050: *
051: * This software consists of voluntary contributions made by many
052: * individuals on behalf of the Apache Software Foundation. For more
053: * information on the Apache Software Foundation, please see
054: * <http://www.apache.org/>.
055: *
056: * Original code Copyright 2000 Quadcap Software:
057: * This software may be freely redistributed in source or binary form
058: * for any purpose.
059: *
060: */
061:
062: package org.apache.catalina.util;
063:
064: import java.util.Date;
065:
066: import java.text.DateFormat;
067: import java.text.FieldPosition;
068: import java.text.ParsePosition;
069: import java.text.SimpleDateFormat;
070:
071: /**
072: * Fast date formatter that caches recently formatted date information
073: * and uses it to avoid too-frequent calls to the underlying
074: * formatter. Note: breaks fieldPosition param of format(Date,
075: * StringBuffer, FieldPosition). If you care about the field
076: * position, call the underlying DateFormat directly.
077: *
078: * @author Stan Bailes
079: * @author Alex Chaffee
080: **/
081: public class FastDateFormat extends DateFormat {
082: DateFormat df;
083: long lastSec = -1;
084: StringBuffer sb = new StringBuffer();
085: FieldPosition fp = new FieldPosition(DateFormat.MILLISECOND_FIELD);
086:
087: public FastDateFormat(DateFormat df) {
088: this .df = df;
089: }
090:
091: public Date parse(String text, ParsePosition pos) {
092: return df.parse(text, pos);
093: }
094:
095: /**
096: * Note: breaks functionality of fieldPosition param. Also:
097: * there's a bug in SimpleDateFormat with "S" and "SS", use "SSS"
098: * instead if you want a msec field.
099: **/
100: public StringBuffer format(Date date, StringBuffer toAppendTo,
101: FieldPosition fieldPosition) {
102: long dt = date.getTime();
103: long ds = dt / 1000;
104: if (ds != lastSec) {
105: sb.setLength(0);
106: df.format(date, sb, fp);
107: lastSec = ds;
108: } else {
109: // munge current msec into existing string
110: int ms = (int) (dt % 1000);
111: int pos = fp.getEndIndex();
112: int begin = fp.getBeginIndex();
113: if (pos > 0) {
114: if (pos > begin)
115: sb
116: .setCharAt(--pos, Character.forDigit(
117: ms % 10, 10));
118: ms /= 10;
119: if (pos > begin)
120: sb
121: .setCharAt(--pos, Character.forDigit(
122: ms % 10, 10));
123: ms /= 10;
124: if (pos > begin)
125: sb
126: .setCharAt(--pos, Character.forDigit(
127: ms % 10, 10));
128: }
129: }
130: toAppendTo.append(sb.toString());
131: return toAppendTo;
132: }
133:
134: public static void main(String[] args) {
135: String format = "yyyy-MM-dd HH:mm:ss.SSS";
136: if (args.length > 0)
137: format = args[0];
138: SimpleDateFormat sdf = new SimpleDateFormat(format);
139: FastDateFormat fdf = new FastDateFormat(sdf);
140: Date d = new Date();
141:
142: d.setTime(1);
143: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
144: d.setTime(20);
145: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
146: d.setTime(500);
147: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
148: d.setTime(543);
149: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
150: d.setTime(999);
151: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
152: d.setTime(1050);
153: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
154: d.setTime(2543);
155: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
156: d.setTime(12345);
157: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
158: d.setTime(12340);
159: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
160:
161: final int reps = 100000;
162: {
163: long start = System.currentTimeMillis();
164: for (int i = 0; i < reps; i++) {
165: d.setTime(System.currentTimeMillis());
166: fdf.format(d);
167: }
168: long elap = System.currentTimeMillis() - start;
169: System.out.println("fast: " + elap + " elapsed");
170: System.out.println(fdf.format(d));
171: }
172: {
173: long start = System.currentTimeMillis();
174: for (int i = 0; i < reps; i++) {
175: d.setTime(System.currentTimeMillis());
176: sdf.format(d);
177: }
178: long elap = System.currentTimeMillis() - start;
179: System.out.println("slow: " + elap + " elapsed");
180: System.out.println(sdf.format(d));
181: }
182: }
183: }
|