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
// ========================================================================
15
package org.mortbay.util;
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;
23
/* ------------------------------------------------------------ */
24
/** Date Format Cache.
25
* Computes String representations of Dates and caches
26
* the results so that subsequent requests within the same minute
29
* Only format strings that contain either "ss" or "ss.SSS" are
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.
35
* If consecutive calls are frequently very different, then this
36
* may be a little slower than a normal DateFormat.
38
* @author Kent Johnson <KJohnson@transparent.com>
39
* @author Greg Wilkins (gregw)
42
public class DateCache
44
public static String DEFAULT_FORMAT="EEE MMM dd HH:mm:ss zzz yyyy";
45
private static long __hitWindow=60*60;
47
private String _formatString;
48
private String _tzFormatString;
49
private SimpleDateFormat _tzFormat;
51
private String _minFormatString;
52
private SimpleDateFormat _minFormat;
54
private String _secFormatString;
55
private String _secFormatString0;
56
private String _secFormatString1;
58
private long _lastMinutes = -1;
59
private long _lastSeconds = -1;
60
private int _lastMs = -1;
61
private String _lastResult = null;
63
private Locale _locale = null;
64
private DateFormatSymbols _dfs = null;
66
/* ------------------------------------------------------------ */
68
* Make a DateCache that will use a default format. The default format
69
* generates the same results as Date.toString().
74
getFormat().setTimeZone(TimeZone.getDefault());
77
/* ------------------------------------------------------------ */
79
* Make a DateCache that will use the given format
81
public DateCache(String format)
84
setTimeZone(TimeZone.getDefault());
88
/* ------------------------------------------------------------ */
89
public DateCache(String format,Locale l)
93
setTimeZone(TimeZone.getDefault());
96
/* ------------------------------------------------------------ */
97
public DateCache(String format,DateFormatSymbols s)
101
setTimeZone(TimeZone.getDefault());
104
/* ------------------------------------------------------------ */
105
/** Set the timezone.
108
public void setTimeZone(TimeZone tz)
110
setTzFormatString(tz);
111
if( _locale != null )
113
_tzFormat=new SimpleDateFormat(_tzFormatString,_locale);
114
_minFormat=new SimpleDateFormat(_minFormatString,_locale);
116
else if( _dfs != null )
118
_tzFormat=new SimpleDateFormat(_tzFormatString,_dfs);
119
_minFormat=new SimpleDateFormat(_minFormatString,_dfs);
123
_tzFormat=new SimpleDateFormat(_tzFormatString);
124
_minFormat=new SimpleDateFormat(_minFormatString);
126
_tzFormat.setTimeZone(tz);
127
_minFormat.setTimeZone(tz);
132
/* ------------------------------------------------------------ */
133
public TimeZone getTimeZone()
135
return _tzFormat.getTimeZone();
138
/* ------------------------------------------------------------ */
139
/** Set the timezone.
140
* @param timeZoneId TimeZoneId the ID of the zone as used by
141
* TimeZone.getTimeZone(id)
143
public void setTimeZoneID(String timeZoneId)
145
setTimeZone(TimeZone.getTimeZone(timeZoneId));
148
/* ------------------------------------------------------------ */
149
private void setTzFormatString(final TimeZone tz )
151
int zIndex = _formatString.indexOf( "ZZZ" );
154
String ss1 = _formatString.substring( 0, zIndex );
155
String ss2 = _formatString.substring( zIndex+3 );
156
int tzOffset = tz.getRawOffset();
158
StringBuffer sb = new StringBuffer(_formatString.length()+10);
165
tzOffset = -tzOffset;
169
int raw = tzOffset / (1000*60); // Convert to seconds
182
_tzFormatString=sb.toString();
185
_tzFormatString=_formatString;
186
setMinFormatString();
190
/* ------------------------------------------------------------ */
191
private void setMinFormatString()
193
int i = _tzFormatString.indexOf("ss.SSS");
196
throw new IllegalStateException("ms not supported");
197
i = _tzFormatString.indexOf("ss");
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;
206
/* ------------------------------------------------------------ */
207
/** Format a date according to our stored formatter.
209
* @return Formatted date
211
public synchronized String format(Date inDate)
213
return format(inDate.getTime());
216
/* ------------------------------------------------------------ */
217
/** Format a date according to our stored formatter.
219
* @return Formatted date
221
public synchronized String format(long inDate)
223
long seconds = inDate / 1000;
225
// Is it not suitable to cache?
226
if (seconds<_lastSeconds ||
227
_lastSeconds>0 && seconds>_lastSeconds+__hitWindow)
230
Date d = new Date(inDate);
231
return _tzFormat.format(d);
235
// Check if we are in the same second
236
// and don't care about millis
237
if (_lastSeconds==seconds )
240
Date d = new Date(inDate);
242
// Check if we need a new format string
243
long minutes = seconds/60;
244
if (_lastMinutes != minutes)
246
_lastMinutes = minutes;
247
_secFormatString=_minFormat.format(d);
249
int i=_secFormatString.indexOf("ss");
251
_secFormatString0=_secFormatString.substring(0,i);
252
_secFormatString1=_secFormatString.substring(i+l);
255
// Always format if we get here
256
_lastSeconds = seconds;
257
StringBuffer sb=new StringBuffer(_secFormatString.length());
260
sb.append(_secFormatString0);
261
int s=(int)(seconds%60);
265
sb.append(_secFormatString1);
266
_lastResult=sb.toString();
272
/* ------------------------------------------------------------ */
273
/** Format to string buffer.
274
* @param inDate Date the format
275
* @param buffer StringBuffer
277
public void format(long inDate, StringBuffer buffer)
279
buffer.append(format(inDate));
282
/* ------------------------------------------------------------ */
285
public SimpleDateFormat getFormat()
290
/* ------------------------------------------------------------ */
291
public String getFormatString()
293
return _formatString;
296
/* ------------------------------------------------------------ */
299
long now=System.currentTimeMillis();
300
_lastMs=(int)(now%1000);
304
/* ------------------------------------------------------------ */