Mega Code Archive

 
Categories / Java / Data Type
 

Date Format Cache

//  // Copyright 2004-2005 Mort Bay Consulting Pty. Ltd. // ------------------------------------------------------------------------ // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at  // http://www.apache.org/licenses/LICENSE-2.0 // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. //  import java.text.DateFormatSymbols; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Locale; import java.util.TimeZone; /* ------------------------------------------------------------ */ /**  Date Format Cache.  * Computes String representations of Dates and caches  * the results so that subsequent requests within the same minute  * will be fast.  *  * Only format strings that contain either "ss" or "ss.SSS" are  * handled.  *  * The timezone of the date may be included as an ID with the "zzz"  * format string or as an offset with the "ZZZ" format string.  *  * If consecutive calls are frequently very different, then this  * may be a little slower than a normal DateFormat.  *  * @author Kent Johnson <KJohnson@transparent.com>  * @author Greg Wilkins (gregw)  */ public class DateCache   {     private static long __hitWindow=60*60;     private static long __MaxMisses=10;          private String _formatString;     private String _tzFormatString;     private SimpleDateFormat _tzFormat;          private String _minFormatString;     private SimpleDateFormat _minFormat;     private String _secFormatString;     private String _secFormatString0;     private String _secFormatString1;     private boolean _millis=false;     private long _misses = 0;     private long _lastMinutes = -1;     private long _lastSeconds = -1;     private String _lastResult = null;     private Locale _locale  = null;     private DateFormatSymbols _dfs  = null;     /* ------------------------------------------------------------ */     /** Constructor.      * Make a DateCache that will use a default format. The default format      * generates the same results as Date.toString().      */     public DateCache()     {         this("EEE MMM dd HH:mm:ss zzz yyyy");         getFormat().setTimeZone(TimeZone.getDefault());     }          /* ------------------------------------------------------------ */     /** Constructor.      * Make a DateCache that will use the given format      */     public DateCache(String format)     {         _formatString=format;         setTimeZone(TimeZone.getDefault());              }          /* ------------------------------------------------------------ */     public DateCache(String format,Locale l)     {         _formatString=format;         _locale = l;         setTimeZone(TimeZone.getDefault());            }          /* ------------------------------------------------------------ */     public DateCache(String format,DateFormatSymbols s)     {         _formatString=format;         _dfs = s;         setTimeZone(TimeZone.getDefault());     }     /* ------------------------------------------------------------ */     /** Set the timezone.      * @param tz TimeZone      */     public void setTimeZone(TimeZone tz)     {         setTzFormatString(tz);                 if( _locale != null )          {             _tzFormat=new SimpleDateFormat(_tzFormatString,_locale);             _minFormat=new SimpleDateFormat(_minFormatString,_locale);         }         else if( _dfs != null )          {             _tzFormat=new SimpleDateFormat(_tzFormatString,_dfs);             _minFormat=new SimpleDateFormat(_minFormatString,_dfs);         }         else          {             _tzFormat=new SimpleDateFormat(_tzFormatString);             _minFormat=new SimpleDateFormat(_minFormatString);         }         _tzFormat.setTimeZone(tz);         _minFormat.setTimeZone(tz);         _lastSeconds=-1;         _lastMinutes=-1;             }     /* ------------------------------------------------------------ */     public TimeZone getTimeZone()     {         return _tzFormat.getTimeZone();     }          /* ------------------------------------------------------------ */     /** Set the timezone.      * @param timeZoneId TimeZoneId the ID of the zone as used by      * TimeZone.getTimeZone(id)      */     public void setTimeZoneID(String timeZoneId)     {         setTimeZone(TimeZone.getTimeZone(timeZoneId));     }          /* ------------------------------------------------------------ */     private void setTzFormatString(final  TimeZone tz )     {         int zIndex = _formatString.indexOf( "ZZZ" );         if( zIndex >= 0 )         {             String ss1 = _formatString.substring( 0, zIndex );             String ss2 = _formatString.substring( zIndex+3 );             int tzOffset = tz.getRawOffset();                          StringBuffer sb = new StringBuffer(_formatString.length()+10);             sb.append(ss1);             sb.append("'");             if( tzOffset >= 0 )                 sb.append( '+' );             else             {                 tzOffset = -tzOffset;                 sb.append( '-' );             }                          int raw = tzOffset / (1000*60);   // Convert to seconds             int hr = raw / 60;             int min = raw % 60;                          if( hr < 10 )                 sb.append( '0' );             sb.append( hr );             if( min < 10 )                 sb.append( '0' );             sb.append( min );             sb.append( '\'' );                          sb.append(ss2);             _tzFormatString=sb.toString();                     }         else             _tzFormatString=_formatString;         setMinFormatString();     }          /* ------------------------------------------------------------ */     private void setMinFormatString()     {         int i = _tzFormatString.indexOf("ss.SSS");         int l = 6;         if (i>=0)             _millis=true;         else         {             i = _tzFormatString.indexOf("ss");             l=2;         }                  // Build a formatter that formats a second format string         // Have to replace @ with ' later due to bug in SimpleDateFormat         String ss1=_tzFormatString.substring(0,i);         String ss2=_tzFormatString.substring(i+l);         _minFormatString =ss1+(_millis?"'ss.SSS'":"'ss'")+ss2;     }     /* ------------------------------------------------------------ */     /** Format a date according to our stored formatter.      * @param inDate       * @return Formatted date      */     public synchronized String format(Date inDate)     {         return format(inDate.getTime());     }          /* ------------------------------------------------------------ */     /** Format a date according to our stored formatter.      * @param inDate       * @return Formatted date      */     public synchronized String format(long inDate)     {         long seconds = inDate / 1000;         // Is it not suitable to cache?         if (seconds<_lastSeconds ||             _lastSeconds>0 && seconds>_lastSeconds+__hitWindow)         {             // It's a cache miss             _misses++;             if (_misses<__MaxMisses)             {                 Date d = new Date(inDate);                 return _tzFormat.format(d);             }             }         else if (_misses>0)             _misses--;                                                    // Check if we are in the same second         // and don't care about millis         if (_lastSeconds==seconds && !_millis)             return _lastResult;         Date d = new Date(inDate);                  // Check if we need a new format string         long minutes = seconds/60;         if (_lastMinutes != minutes)         {             _lastMinutes = minutes;             _secFormatString=_minFormat.format(d);             int i;             int l;             if (_millis)             {                 i=_secFormatString.indexOf("ss.SSS");                 l=6;             }             else             {                 i=_secFormatString.indexOf("ss");                 l=2;             }             _secFormatString0=_secFormatString.substring(0,i);             _secFormatString1=_secFormatString.substring(i+l);         }         // Always format if we get here         _lastSeconds = seconds;         StringBuffer sb=new StringBuffer(_secFormatString.length());         synchronized(sb)         {             sb.append(_secFormatString0);             int s=(int)(seconds%60);             if (s<10)                 sb.append('0');             sb.append(s);             if (_millis)             {                 long millis = inDate%1000;                 if (millis<10)                     sb.append(".00");                 else if (millis<100)                     sb.append(".0");                 else                     sb.append('.');                 sb.append(millis);             }             sb.append(_secFormatString1);             _lastResult=sb.toString();         }                          return _lastResult;     }     /* ------------------------------------------------------------ */     /** Format to string buffer.       * @param inDate Date the format      * @param buffer StringBuffer      */     public void format(long inDate, StringBuffer buffer)     {         buffer.append(format(inDate));     }          /* ------------------------------------------------------------ */     /** Get the format.      */     public SimpleDateFormat getFormat()     {         return _minFormat;     }     /* ------------------------------------------------------------ */     public String getFormatString()     {         return _formatString;     }         /* ------------------------------------------------------------ */     public String now()     {         return format(System.currentTimeMillis());     } }