]> WPIA git - gigi.git/blob - lib/jetty/org/eclipse/jetty/util/DateCache.java
Merge "Update notes about password security"
[gigi.git] / lib / jetty / org / eclipse / jetty / util / DateCache.java
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2016 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.
8 //
9 //      The Eclipse Public License is available at
10 //      http://www.eclipse.org/legal/epl-v10.html
11 //
12 //      The Apache License v2.0 is available at
13 //      http://www.opensource.org/licenses/apache2.0.php
14 //
15 //  You may elect to redistribute this code under either of these licenses.
16 //  ========================================================================
17 //
18
19 package org.eclipse.jetty.util;
20
21 import java.text.SimpleDateFormat;
22 import java.util.Date;
23 import java.util.Locale;
24 import java.util.TimeZone;
25
26 /* ------------------------------------------------------------ */
27 /**  Date Format Cache.
28  * Computes String representations of Dates and caches
29  * the results so that subsequent requests within the same second
30  * will be fast.
31  *
32  * Only format strings that contain either "ss".  Sub second formatting is 
33  * not handled.
34  *
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.
37  *
38  * If consecutive calls are frequently very different, then this
39  * may be a little slower than a normal DateFormat.
40  *
41  */
42
43 public class DateCache
44 {
45     public static final String DEFAULT_FORMAT="EEE MMM dd HH:mm:ss zzz yyyy";
46     
47     private final String _formatString;
48     private final String _tzFormatString;
49     private final SimpleDateFormat _tzFormat;
50     private final Locale _locale ;
51     
52     private volatile Tick _tick;
53
54     /* ------------------------------------------------------------ */
55     /* ------------------------------------------------------------ */
56     public static class Tick
57     {
58         final long _seconds;
59         final String _string;
60         public Tick(long seconds, String string)
61         {
62             _seconds = seconds;
63             _string = string;
64         }
65     }
66
67     /* ------------------------------------------------------------ */
68     /** Constructor.
69      * Make a DateCache that will use a default format. The default format
70      * generates the same results as Date.toString().
71      */
72     public DateCache()
73     {
74         this(DEFAULT_FORMAT);
75     }
76     
77     /* ------------------------------------------------------------ */
78     /** Constructor.
79      * Make a DateCache that will use the given format
80      */
81     public DateCache(String format)
82     {
83         this(format,null,TimeZone.getDefault());
84     }
85     
86     /* ------------------------------------------------------------ */
87     public DateCache(String format,Locale l)
88     {
89         this(format,l,TimeZone.getDefault());
90     }
91
92     /* ------------------------------------------------------------ */
93     public DateCache(String format,Locale l,String tz)
94     {
95         this(format,l,TimeZone.getTimeZone(tz));
96     }
97     
98     /* ------------------------------------------------------------ */
99     public DateCache(String format,Locale l,TimeZone tz)
100     {
101         _formatString=format;
102         _locale = l;
103         
104
105         int zIndex = _formatString.indexOf( "ZZZ" );
106         if( zIndex >= 0 )
107         {
108             String ss1 = _formatString.substring( 0, zIndex );
109             String ss2 = _formatString.substring( zIndex+3 );
110             int tzOffset = tz.getRawOffset();
111             
112             StringBuilder sb = new StringBuilder(_formatString.length()+10);
113             sb.append(ss1);
114             sb.append("'");
115             if( tzOffset >= 0 )
116                 sb.append( '+' );
117             else
118             {
119                 tzOffset = -tzOffset;
120                 sb.append( '-' );
121             }
122             
123             int raw = tzOffset / (1000*60);             // Convert to seconds
124             int hr = raw / 60;
125             int min = raw % 60;
126             
127             if( hr < 10 )
128                 sb.append( '0' );
129             sb.append( hr );
130             if( min < 10 )
131                 sb.append( '0' );
132             sb.append( min );
133             sb.append( '\'' );
134             
135             sb.append(ss2);
136             _tzFormatString=sb.toString();            
137         }
138         else
139             _tzFormatString=_formatString;
140    
141         if( _locale != null ) 
142         {
143             _tzFormat=new SimpleDateFormat(_tzFormatString,_locale);
144         }
145         else 
146         {
147             _tzFormat=new SimpleDateFormat(_tzFormatString);
148         }
149         _tzFormat.setTimeZone(tz);
150         
151         _tick=null;
152     }
153     
154
155     /* ------------------------------------------------------------ */
156     public TimeZone getTimeZone()
157     {
158         return _tzFormat.getTimeZone();
159     }
160
161
162     /* ------------------------------------------------------------ */
163     /** Format a date according to our stored formatter.
164      * @param inDate 
165      * @return Formatted date
166      */
167     public String format(Date inDate)
168     {
169         long seconds = inDate.getTime() / 1000;
170
171         Tick tick=_tick;
172         
173         // Is this the cached time
174         if (tick==null || seconds!=tick._seconds)
175         {
176             // It's a cache miss
177             synchronized (this)
178             {
179                 return _tzFormat.format(inDate);
180             }
181         }
182         
183         return tick._string;
184     }
185     
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.
190      * @param inDate 
191      * @return Formatted date
192      */
193     public String format(long inDate)
194     {
195         long seconds = inDate / 1000;
196
197         Tick tick=_tick;
198         
199         // Is this the cached time
200         if (tick==null || seconds!=tick._seconds)
201         {
202             // It's a cache miss
203             Date d = new Date(inDate);
204             synchronized (this)
205             {
206                 return _tzFormat.format(d);
207             }
208         }
209         
210         return tick._string;
211     }
212     
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.
218      * @param now 
219      * @return Formatted date
220      */
221     public String formatNow(long now)
222     {
223         long seconds = now / 1000;
224
225         Tick tick=_tick;
226         
227         // Is this the cached time
228         if (tick!=null && tick._seconds==seconds)
229             return tick._string;
230         return formatTick(now)._string;
231     }
232     
233     /* ------------------------------------------------------------ */
234     public String now()
235     {
236         return formatNow(System.currentTimeMillis());
237     }
238     
239     /* ------------------------------------------------------------ */
240     public Tick tick()
241     {
242         return formatTick(System.currentTimeMillis());
243     }
244     
245     /* ------------------------------------------------------------ */
246     protected Tick formatTick(long now)
247     {
248         long seconds = now / 1000;
249
250         // Synchronize to protect _tzFormat
251         synchronized (this)
252         {
253             // recheck the tick, to save multiple formats
254             if (_tick==null || _tick._seconds!=seconds)
255             {
256                 String s= _tzFormat.format(new Date(now));
257                 return _tick=new Tick(seconds,s);
258             }
259             return _tick;
260         }
261     }
262
263     /* ------------------------------------------------------------ */
264     public String getFormatString()
265     {
266         return _formatString;
267     }    
268 }