001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.catalina.util;
019:
020: import java.util.Date;
021:
022: import java.text.DateFormat;
023: import java.text.FieldPosition;
024: import java.text.ParsePosition;
025: import java.text.SimpleDateFormat;
026:
027: /**
028: * Fast date formatter that caches recently formatted date information
029: * and uses it to avoid too-frequent calls to the underlying
030: * formatter. Note: breaks fieldPosition param of format(Date,
031: * StringBuffer, FieldPosition). If you care about the field
032: * position, call the underlying DateFormat directly.
033: *
034: * @author Stan Bailes
035: * @author Alex Chaffee
036: **/
037: public class FastDateFormat extends DateFormat {
038: DateFormat df;
039: long lastSec = -1;
040: StringBuffer sb = new StringBuffer();
041: FieldPosition fp = new FieldPosition(DateFormat.MILLISECOND_FIELD);
042:
043: public FastDateFormat(DateFormat df) {
044: this .df = df;
045: }
046:
047: public Date parse(String text, ParsePosition pos) {
048: return df.parse(text, pos);
049: }
050:
051: /**
052: * Note: breaks functionality of fieldPosition param. Also:
053: * there's a bug in SimpleDateFormat with "S" and "SS", use "SSS"
054: * instead if you want a msec field.
055: **/
056: public StringBuffer format(Date date, StringBuffer toAppendTo,
057: FieldPosition fieldPosition) {
058: long dt = date.getTime();
059: long ds = dt / 1000;
060: if (ds != lastSec) {
061: sb.setLength(0);
062: df.format(date, sb, fp);
063: lastSec = ds;
064: } else {
065: // munge current msec into existing string
066: int ms = (int) (dt % 1000);
067: int pos = fp.getEndIndex();
068: int begin = fp.getBeginIndex();
069: if (pos > 0) {
070: if (pos > begin)
071: sb
072: .setCharAt(--pos, Character.forDigit(
073: ms % 10, 10));
074: ms /= 10;
075: if (pos > begin)
076: sb
077: .setCharAt(--pos, Character.forDigit(
078: ms % 10, 10));
079: ms /= 10;
080: if (pos > begin)
081: sb
082: .setCharAt(--pos, Character.forDigit(
083: ms % 10, 10));
084: }
085: }
086: toAppendTo.append(sb.toString());
087: return toAppendTo;
088: }
089:
090: public static void main(String[] args) {
091: String format = "yyyy-MM-dd HH:mm:ss.SSS";
092: if (args.length > 0)
093: format = args[0];
094: SimpleDateFormat sdf = new SimpleDateFormat(format);
095: FastDateFormat fdf = new FastDateFormat(sdf);
096: Date d = new Date();
097:
098: d.setTime(1);
099: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
100: d.setTime(20);
101: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
102: d.setTime(500);
103: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
104: d.setTime(543);
105: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
106: d.setTime(999);
107: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
108: d.setTime(1050);
109: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
110: d.setTime(2543);
111: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
112: d.setTime(12345);
113: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
114: d.setTime(12340);
115: System.out.println(fdf.format(d) + "\t" + sdf.format(d));
116:
117: final int reps = 100000;
118: {
119: long start = System.currentTimeMillis();
120: for (int i = 0; i < reps; i++) {
121: d.setTime(System.currentTimeMillis());
122: fdf.format(d);
123: }
124: long elap = System.currentTimeMillis() - start;
125: System.out.println("fast: " + elap + " elapsed");
126: System.out.println(fdf.format(d));
127: }
128: {
129: long start = System.currentTimeMillis();
130: for (int i = 0; i < reps; i++) {
131: d.setTime(System.currentTimeMillis());
132: sdf.format(d);
133: }
134: long elap = System.currentTimeMillis() - start;
135: System.out.println("slow: " + elap + " elapsed");
136: System.out.println(sdf.format(d));
137: }
138: }
139: }
|