~ubuntu-branches/ubuntu/utopic/jetty/utopic-proposed

« back to all changes in this revision

Viewing changes to modules/util/src/main/java/org/mortbay/util/DateCache.java

  • Committer: Bazaar Package Importer
  • Author(s): Torsten Werner
  • Date: 2009-08-09 08:48:10 UTC
  • Revision ID: james.westby@ubuntu.com-20090809084810-k522b97ind2robyd
ImportĀ upstreamĀ versionĀ 6.1.19

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ========================================================================
 
2
// Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
 
3
// ------------------------------------------------------------------------
 
4
// Licensed under the Apache License, Version 2.0 (the "License");
 
5
// you may not use this file except in compliance with the License.
 
6
// You may obtain a copy of the License at 
 
7
// http://www.apache.org/licenses/LICENSE-2.0
 
8
// Unless required by applicable law or agreed to in writing, software
 
9
// distributed under the License is distributed on an "AS IS" BASIS,
 
10
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
11
// See the License for the specific language governing permissions and
 
12
// limitations under the License.
 
13
// ========================================================================
 
14
 
 
15
package org.mortbay.util;
 
16
 
 
17
import java.text.DateFormatSymbols;
 
18
import java.text.SimpleDateFormat;
 
19
import java.util.Date;
 
20
import java.util.Locale;
 
21
import java.util.TimeZone;
 
22
 
 
23
/* ------------------------------------------------------------ */
 
24
/**  Date Format Cache.
 
25
 * Computes String representations of Dates and caches
 
26
 * the results so that subsequent requests within the same minute
 
27
 * will be fast.
 
28
 *
 
29
 * Only format strings that contain either "ss" or "ss.SSS" are
 
30
 * handled.
 
31
 *
 
32
 * The timezone of the date may be included as an ID with the "zzz"
 
33
 * format string or as an offset with the "ZZZ" format string.
 
34
 *
 
35
 * If consecutive calls are frequently very different, then this
 
36
 * may be a little slower than a normal DateFormat.
 
37
 *
 
38
 * @author Kent Johnson <KJohnson@transparent.com>
 
39
 * @author Greg Wilkins (gregw)
 
40
 */
 
41
 
 
42
public class DateCache  
 
43
{
 
44
    public static String DEFAULT_FORMAT="EEE MMM dd HH:mm:ss zzz yyyy";
 
45
    private static long __hitWindow=60*60;
 
46
    
 
47
    private String _formatString;
 
48
    private String _tzFormatString;
 
49
    private SimpleDateFormat _tzFormat;
 
50
    
 
51
    private String _minFormatString;
 
52
    private SimpleDateFormat _minFormat;
 
53
 
 
54
    private String _secFormatString;
 
55
    private String _secFormatString0;
 
56
    private String _secFormatString1;
 
57
 
 
58
    private long _lastMinutes = -1;
 
59
    private long _lastSeconds = -1;
 
60
    private int _lastMs = -1;
 
61
    private String _lastResult = null;
 
62
 
 
63
    private Locale _locale      = null;
 
64
    private DateFormatSymbols   _dfs    = null;
 
65
 
 
66
    /* ------------------------------------------------------------ */
 
67
    /** Constructor.
 
68
     * Make a DateCache that will use a default format. The default format
 
69
     * generates the same results as Date.toString().
 
70
     */
 
71
    public DateCache()
 
72
    {
 
73
        this(DEFAULT_FORMAT);
 
74
        getFormat().setTimeZone(TimeZone.getDefault());
 
75
    }
 
76
    
 
77
    /* ------------------------------------------------------------ */
 
78
    /** Constructor.
 
79
     * Make a DateCache that will use the given format
 
80
     */
 
81
    public DateCache(String format)
 
82
    {
 
83
        _formatString=format;
 
84
        setTimeZone(TimeZone.getDefault());
 
85
        
 
86
    }
 
87
    
 
88
    /* ------------------------------------------------------------ */
 
89
    public DateCache(String format,Locale l)
 
90
    {
 
91
        _formatString=format;
 
92
        _locale = l;
 
93
        setTimeZone(TimeZone.getDefault());       
 
94
    }
 
95
    
 
96
    /* ------------------------------------------------------------ */
 
97
    public DateCache(String format,DateFormatSymbols s)
 
98
    {
 
99
        _formatString=format;
 
100
        _dfs = s;
 
101
        setTimeZone(TimeZone.getDefault());
 
102
    }
 
103
 
 
104
    /* ------------------------------------------------------------ */
 
105
    /** Set the timezone.
 
106
     * @param tz TimeZone
 
107
     */
 
108
    public void setTimeZone(TimeZone tz)
 
109
    {
 
110
        setTzFormatString(tz);        
 
111
        if( _locale != null ) 
 
112
        {
 
113
            _tzFormat=new SimpleDateFormat(_tzFormatString,_locale);
 
114
            _minFormat=new SimpleDateFormat(_minFormatString,_locale);
 
115
        }
 
116
        else if( _dfs != null ) 
 
117
        {
 
118
            _tzFormat=new SimpleDateFormat(_tzFormatString,_dfs);
 
119
            _minFormat=new SimpleDateFormat(_minFormatString,_dfs);
 
120
        }
 
121
        else 
 
122
        {
 
123
            _tzFormat=new SimpleDateFormat(_tzFormatString);
 
124
            _minFormat=new SimpleDateFormat(_minFormatString);
 
125
        }
 
126
        _tzFormat.setTimeZone(tz);
 
127
        _minFormat.setTimeZone(tz);
 
128
        _lastSeconds=-1;
 
129
        _lastMinutes=-1;        
 
130
    }
 
131
 
 
132
    /* ------------------------------------------------------------ */
 
133
    public TimeZone getTimeZone()
 
134
    {
 
135
        return _tzFormat.getTimeZone();
 
136
    }
 
137
    
 
138
    /* ------------------------------------------------------------ */
 
139
    /** Set the timezone.
 
140
     * @param timeZoneId TimeZoneId the ID of the zone as used by
 
141
     * TimeZone.getTimeZone(id)
 
142
     */
 
143
    public void setTimeZoneID(String timeZoneId)
 
144
    {
 
145
        setTimeZone(TimeZone.getTimeZone(timeZoneId));
 
146
    }
 
147
    
 
148
    /* ------------------------------------------------------------ */
 
149
    private void setTzFormatString(final  TimeZone tz )
 
150
    {
 
151
        int zIndex = _formatString.indexOf( "ZZZ" );
 
152
        if( zIndex >= 0 )
 
153
        {
 
154
            String ss1 = _formatString.substring( 0, zIndex );
 
155
            String ss2 = _formatString.substring( zIndex+3 );
 
156
            int tzOffset = tz.getRawOffset();
 
157
            
 
158
            StringBuffer sb = new StringBuffer(_formatString.length()+10);
 
159
            sb.append(ss1);
 
160
            sb.append("'");
 
161
            if( tzOffset >= 0 )
 
162
                sb.append( '+' );
 
163
            else
 
164
            {
 
165
                tzOffset = -tzOffset;
 
166
                sb.append( '-' );
 
167
            }
 
168
            
 
169
            int raw = tzOffset / (1000*60);             // Convert to seconds
 
170
            int hr = raw / 60;
 
171
            int min = raw % 60;
 
172
            
 
173
            if( hr < 10 )
 
174
                sb.append( '0' );
 
175
            sb.append( hr );
 
176
            if( min < 10 )
 
177
                sb.append( '0' );
 
178
            sb.append( min );
 
179
            sb.append( '\'' );
 
180
            
 
181
            sb.append(ss2);
 
182
            _tzFormatString=sb.toString();            
 
183
        }
 
184
        else
 
185
            _tzFormatString=_formatString;
 
186
        setMinFormatString();
 
187
    }
 
188
 
 
189
    
 
190
    /* ------------------------------------------------------------ */
 
191
    private void setMinFormatString()
 
192
    {
 
193
        int i = _tzFormatString.indexOf("ss.SSS");
 
194
        int l = 6;
 
195
        if (i>=0)
 
196
            throw new IllegalStateException("ms not supported");
 
197
        i = _tzFormatString.indexOf("ss");
 
198
        l=2;
 
199
        
 
200
        // Build a formatter that formats a second format string
 
201
        String ss1=_tzFormatString.substring(0,i);
 
202
        String ss2=_tzFormatString.substring(i+l);
 
203
        _minFormatString =ss1+"'ss'"+ss2;
 
204
    }
 
205
 
 
206
    /* ------------------------------------------------------------ */
 
207
    /** Format a date according to our stored formatter.
 
208
     * @param inDate 
 
209
     * @return Formatted date
 
210
     */
 
211
    public synchronized String format(Date inDate)
 
212
    {
 
213
        return format(inDate.getTime());
 
214
    }
 
215
    
 
216
    /* ------------------------------------------------------------ */
 
217
    /** Format a date according to our stored formatter.
 
218
     * @param inDate 
 
219
     * @return Formatted date
 
220
     */
 
221
    public synchronized String format(long inDate)
 
222
    {
 
223
        long seconds = inDate / 1000;
 
224
 
 
225
        // Is it not suitable to cache?
 
226
        if (seconds<_lastSeconds ||
 
227
            _lastSeconds>0 && seconds>_lastSeconds+__hitWindow)
 
228
        {
 
229
            // It's a cache miss
 
230
            Date d = new Date(inDate);
 
231
            return _tzFormat.format(d);
 
232
            
 
233
        }
 
234
                                          
 
235
        // Check if we are in the same second
 
236
        // and don't care about millis
 
237
        if (_lastSeconds==seconds )
 
238
            return _lastResult;
 
239
 
 
240
        Date d = new Date(inDate);
 
241
        
 
242
        // Check if we need a new format string
 
243
        long minutes = seconds/60;
 
244
        if (_lastMinutes != minutes)
 
245
        {
 
246
            _lastMinutes = minutes;
 
247
            _secFormatString=_minFormat.format(d);
 
248
 
 
249
            int i=_secFormatString.indexOf("ss");
 
250
            int l=2;
 
251
            _secFormatString0=_secFormatString.substring(0,i);
 
252
            _secFormatString1=_secFormatString.substring(i+l);
 
253
        }
 
254
 
 
255
        // Always format if we get here
 
256
        _lastSeconds = seconds;
 
257
        StringBuffer sb=new StringBuffer(_secFormatString.length());
 
258
        synchronized(sb)
 
259
        {
 
260
            sb.append(_secFormatString0);
 
261
            int s=(int)(seconds%60);
 
262
            if (s<10)
 
263
                sb.append('0');
 
264
            sb.append(s);
 
265
            sb.append(_secFormatString1);
 
266
            _lastResult=sb.toString();
 
267
        }
 
268
                
 
269
        return _lastResult;
 
270
    }
 
271
 
 
272
    /* ------------------------------------------------------------ */
 
273
    /** Format to string buffer. 
 
274
     * @param inDate Date the format
 
275
     * @param buffer StringBuffer
 
276
     */
 
277
    public void format(long inDate, StringBuffer buffer)
 
278
    {
 
279
        buffer.append(format(inDate));
 
280
    }
 
281
    
 
282
    /* ------------------------------------------------------------ */
 
283
    /** Get the format.
 
284
     */
 
285
    public SimpleDateFormat getFormat()
 
286
    {
 
287
        return _minFormat;
 
288
    }
 
289
 
 
290
    /* ------------------------------------------------------------ */
 
291
    public String getFormatString()
 
292
    {
 
293
        return _formatString;
 
294
    }    
 
295
 
 
296
    /* ------------------------------------------------------------ */
 
297
    public String now()
 
298
    {
 
299
        long now=System.currentTimeMillis();
 
300
        _lastMs=(int)(now%1000);
 
301
        return format(now);
 
302
    }
 
303
 
 
304
    /* ------------------------------------------------------------ */
 
305
    public int lastMs()
 
306
    {
 
307
        return _lastMs;
 
308
    }
 
309
}