/* | |
* 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)); | |
} | |
} | |
} |