1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.jasper.util;
19
20 import java.text.DateFormat;
21 import java.text.FieldPosition;
22 import java.text.ParsePosition;
23 import java.text.SimpleDateFormat;
24 import java.util.Date;
25
26 /***
27 * Fast date formatter that caches recently formatted date information
28 * and uses it to avoid too-frequent calls to the underlying
29 * formatter. Note: breaks fieldPosition param of format(Date,
30 * StringBuffer, FieldPosition). If you care about the field
31 * position, call the underlying DateFormat directly.
32 *
33 * @author Stan Bailes
34 * @author Alex Chaffee
35 */
36 public class FastDateFormat extends DateFormat {
37
38 private DateFormat df;
39 private long lastSec = -1;
40 private StringBuffer sb = new StringBuffer();
41 private FieldPosition fp = new FieldPosition(DateFormat.MILLISECOND_FIELD);
42
43 public FastDateFormat(DateFormat df) {
44 this.df = df;
45 }
46
47 public Date parse(String text, ParsePosition pos) {
48 return df.parse(text, pos);
49 }
50
51 /***
52 * Note: breaks functionality of fieldPosition param. Also:
53 * there's a bug in SimpleDateFormat with "S" and "SS", use "SSS"
54 * instead if you want a msec field.
55 */
56 public StringBuffer format(Date date, StringBuffer toAppendTo,
57 FieldPosition fieldPosition) {
58 long dt = date.getTime();
59 long ds = dt / 1000;
60 if (ds != lastSec) {
61 sb.setLength(0);
62 df.format(date, sb, fp);
63 lastSec = ds;
64 } else {
65
66 int ms = (int) (dt % 1000);
67 int pos = fp.getEndIndex();
68 int begin = fp.getBeginIndex();
69 if (pos > 0) {
70 if (pos > begin)
71 sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
72 ms /= 10;
73 if (pos > begin)
74 sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
75 ms /= 10;
76 if (pos > begin)
77 sb.setCharAt(--pos, Character.forDigit(ms % 10, 10));
78 }
79 }
80 toAppendTo.append(sb.toString());
81 return toAppendTo;
82 }
83
84 public static void main(String[] args) {
85 String format = "yyyy-MM-dd HH:mm:ss.SSS";
86 if (args.length > 0)
87 format = args[0];
88 SimpleDateFormat sdf = new SimpleDateFormat(format);
89 FastDateFormat fdf = new FastDateFormat(sdf);
90 Date d = new Date();
91
92 d.setTime(1);
93 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
94 d.setTime(20);
95 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
96 d.setTime(500);
97 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
98 d.setTime(543);
99 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
100 d.setTime(999);
101 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
102 d.setTime(1050);
103 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
104 d.setTime(2543);
105 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
106 d.setTime(12345);
107 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
108 d.setTime(12340);
109 System.out.println(fdf.format(d) + "\t" + sdf.format(d));
110
111 final int reps = 100000;
112 {
113 long start = System.currentTimeMillis();
114 for (int i = 0; i < reps; i++) {
115 d.setTime(System.currentTimeMillis());
116 fdf.format(d);
117 }
118 long elap = System.currentTimeMillis() - start;
119 System.out.println("fast: " + elap + " elapsed");
120 System.out.println(fdf.format(d));
121 }
122 {
123 long start = System.currentTimeMillis();
124 for (int i = 0; i < reps; i++) {
125 d.setTime(System.currentTimeMillis());
126 sdf.format(d);
127 }
128 long elap = System.currentTimeMillis() - start;
129 System.out.println("slow: " + elap + " elapsed");
130 System.out.println(sdf.format(d));
131 }
132 }
133 }