View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    * 
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   * 
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
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              // munge current msec into existing string
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 }