2 // ========================================================================
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4 // ------------------------------------------------------------------------
5 // All rights reserved. This program and the accompanying materials
6 // are made available under the terms of the Eclipse Public License v1.0
7 // and Apache License v2.0 which accompanies this distribution.
9 // The Eclipse Public License is available at
10 // http://www.eclipse.org/legal/epl-v10.html
12 // The Apache License v2.0 is available at
13 // http://www.opensource.org/licenses/apache2.0.php
15 // You may elect to redistribute this code under either of these licenses.
16 // ========================================================================
19 package org.eclipse.jetty.util;
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23 import java.util.Locale;
24 import java.util.TimeZone;
26 /* ------------------------------------------------------------ */
27 /** Date Format Cache.
28 * Computes String representations of Dates and caches
29 * the results so that subsequent requests within the same second
32 * Only format strings that contain either "ss". Sub second formatting is
35 * The timezone of the date may be included as an ID with the "zzz"
36 * format string or as an offset with the "ZZZ" format string.
38 * If consecutive calls are frequently very different, then this
39 * may be a little slower than a normal DateFormat.
43 public class DateCache
45 public static final String DEFAULT_FORMAT="EEE MMM dd HH:mm:ss zzz yyyy";
47 private final String _formatString;
48 private final String _tzFormatString;
49 private final SimpleDateFormat _tzFormat;
50 private final Locale _locale ;
52 private volatile Tick _tick;
54 /* ------------------------------------------------------------ */
55 /* ------------------------------------------------------------ */
56 public static class Tick
60 public Tick(long seconds, String string)
67 /* ------------------------------------------------------------ */
69 * Make a DateCache that will use a default format. The default format
70 * generates the same results as Date.toString().
77 /* ------------------------------------------------------------ */
79 * Make a DateCache that will use the given format
81 public DateCache(String format)
83 this(format,null,TimeZone.getDefault());
86 /* ------------------------------------------------------------ */
87 public DateCache(String format,Locale l)
89 this(format,l,TimeZone.getDefault());
92 /* ------------------------------------------------------------ */
93 public DateCache(String format,Locale l,String tz)
95 this(format,l,TimeZone.getTimeZone(tz));
98 /* ------------------------------------------------------------ */
99 public DateCache(String format,Locale l,TimeZone tz)
101 _formatString=format;
105 int zIndex = _formatString.indexOf( "ZZZ" );
108 String ss1 = _formatString.substring( 0, zIndex );
109 String ss2 = _formatString.substring( zIndex+3 );
110 int tzOffset = tz.getRawOffset();
112 StringBuilder sb = new StringBuilder(_formatString.length()+10);
119 tzOffset = -tzOffset;
123 int raw = tzOffset / (1000*60); // Convert to seconds
136 _tzFormatString=sb.toString();
139 _tzFormatString=_formatString;
141 if( _locale != null )
143 _tzFormat=new SimpleDateFormat(_tzFormatString,_locale);
147 _tzFormat=new SimpleDateFormat(_tzFormatString);
149 _tzFormat.setTimeZone(tz);
155 /* ------------------------------------------------------------ */
156 public TimeZone getTimeZone()
158 return _tzFormat.getTimeZone();
162 /* ------------------------------------------------------------ */
163 /** Format a date according to our stored formatter.
165 * @return Formatted date
167 public String format(Date inDate)
169 long seconds = inDate.getTime() / 1000;
173 // Is this the cached time
174 if (tick==null || seconds!=tick._seconds)
179 return _tzFormat.format(inDate);
186 /* ------------------------------------------------------------ */
187 /** Format a date according to our stored formatter.
188 * If it happens to be in the same second as the last formatNow
189 * call, then the format is reused.
191 * @return Formatted date
193 public String format(long inDate)
195 long seconds = inDate / 1000;
199 // Is this the cached time
200 if (tick==null || seconds!=tick._seconds)
203 Date d = new Date(inDate);
206 return _tzFormat.format(d);
213 /* ------------------------------------------------------------ */
214 /** Format a date according to our stored formatter.
215 * The passed time is expected to be close to the current time, so it is
216 * compared to the last value passed and if it is within the same second,
217 * the format is reused. Otherwise a new cached format is created.
219 * @return Formatted date
221 public String formatNow(long now)
223 long seconds = now / 1000;
227 // Is this the cached time
228 if (tick!=null && tick._seconds==seconds)
230 return formatTick(now)._string;
233 /* ------------------------------------------------------------ */
236 return formatNow(System.currentTimeMillis());
239 /* ------------------------------------------------------------ */
242 return formatTick(System.currentTimeMillis());
245 /* ------------------------------------------------------------ */
246 protected Tick formatTick(long now)
248 long seconds = now / 1000;
250 // Synchronize to protect _tzFormat
253 // recheck the tick, to save multiple formats
254 if (_tick==null || _tick._seconds!=seconds)
256 String s= _tzFormat.format(new Date(now));
257 return _tick=new Tick(seconds,s);
263 /* ------------------------------------------------------------ */
264 public String getFormatString()
266 return _formatString;