Home » commons-lang-2.4-src » org.apache.commons » lang » time » [javadoc | source]
    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    * 
    9    *      http://www.apache.org/licenses/LICENSE-2.0
   10    * 
   11    * Unless required by applicable law or agreed to in writing, software
   12    * distributed under the License is distributed on an "AS IS" BASIS,
   13    * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    * See the License for the specific language governing permissions and
   15    * limitations under the License.
   16    */
   17   package org.apache.commons.lang.time;
   18   
   19   import java.util.ArrayList;
   20   import java.util.Calendar;
   21   import java.util.Date;
   22   import java.util.GregorianCalendar;
   23   import java.util.TimeZone;
   24   
   25   import org.apache.commons.lang.StringUtils;
   26   
   27   /**
   28    * <p>Duration formatting utilities and constants. The following table describes the tokens 
   29    * used in the pattern language for formatting. </p>
   30    * <table border="1">
   31    *  <tr><th>character</th><th>duration element</th></tr>
   32    *  <tr><td>y</td><td>years</td></tr>
   33    *  <tr><td>M</td><td>months</td></tr>
   34    *  <tr><td>d</td><td>days</td></tr>
   35    *  <tr><td>H</td><td>hours</td></tr>
   36    *  <tr><td>m</td><td>minutes</td></tr>
   37    *  <tr><td>s</td><td>seconds</td></tr>
   38    *  <tr><td>S</td><td>milliseconds</td></tr>
   39    * </table>
   40    *
   41    * @author Apache Ant - DateUtils
   42    * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a>
   43    * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
   44    * @author Stephen Colebourne
   45    * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
   46    * @since 2.1
   47    * @version $Id: DurationFormatUtils.java 583666 2007-10-11 01:38:13Z ggregory $
   48    */
   49   public class DurationFormatUtils {
   50   
   51       /**
   52        * <p>DurationFormatUtils instances should NOT be constructed in standard programming.</p>
   53        *
   54        * <p>This constructor is public to permit tools that require a JavaBean instance
   55        * to operate.</p>
   56        */
   57       public DurationFormatUtils() {
   58           super();
   59       }
   60   
   61       /**
   62        * <p>Pattern used with <code>FastDateFormat</code> and <code>SimpleDateFormat</code>
   63        * for the ISO8601 period format used in durations.</p>
   64        * 
   65        * @see org.apache.commons.lang.time.FastDateFormat
   66        * @see java.text.SimpleDateFormat
   67        */
   68       public static final String ISO_EXTENDED_FORMAT_PATTERN = "'P'yyyy'Y'M'M'd'DT'H'H'm'M's.S'S'";
   69   
   70       //-----------------------------------------------------------------------
   71       /**
   72        * <p>Formats the time gap as a string.</p>
   73        * 
   74        * <p>The format used is ISO8601-like:
   75        * <i>H</i>:<i>m</i>:<i>s</i>.<i>S</i>.</p>
   76        * 
   77        * @param durationMillis  the duration to format
   78        * @return the time as a String
   79        */
   80       public static String formatDurationHMS(long durationMillis) {
   81           return formatDuration(durationMillis, "H:mm:ss.SSS");
   82       }
   83   
   84       /**
   85        * <p>Formats the time gap as a string.</p>
   86        * 
   87        * <p>The format used is the ISO8601 period format.</p>
   88        * 
   89        * <p>This method formats durations using the days and lower fields of the
   90        * ISO format pattern, such as P7D6TH5M4.321S.</p>
   91        * 
   92        * @param durationMillis  the duration to format
   93        * @return the time as a String
   94        */
   95       public static String formatDurationISO(long durationMillis) {
   96           return formatDuration(durationMillis, ISO_EXTENDED_FORMAT_PATTERN, false);
   97       }
   98   
   99       /**
  100        * <p>Formats the time gap as a string, using the specified format, and padding with zeros and 
  101        * using the default timezone.</p>
  102        * 
  103        * <p>This method formats durations using the days and lower fields of the
  104        * format pattern. Months and larger are not used.</p>
  105        * 
  106        * @param durationMillis  the duration to format
  107        * @param format  the way in which to format the duration
  108        * @return the time as a String
  109        */
  110       public static String formatDuration(long durationMillis, String format) {
  111           return formatDuration(durationMillis, format, true);
  112       }
  113   
  114       /**
  115        * <p>Formats the time gap as a string, using the specified format.
  116        * Padding the left hand side of numbers with zeroes is optional and 
  117        * the timezone may be specified.</p>
  118        * 
  119        * <p>This method formats durations using the days and lower fields of the
  120        * format pattern. Months and larger are not used.</p>
  121        * 
  122        * @param durationMillis  the duration to format
  123        * @param format  the way in which to format the duration
  124        * @param padWithZeros  whether to pad the left hand side of numbers with 0's
  125        * @return the time as a String
  126        */
  127       public static String formatDuration(long durationMillis, String format, boolean padWithZeros) {
  128   
  129           Token[] tokens = lexx(format);
  130   
  131           int days         = 0;
  132           int hours        = 0;
  133           int minutes      = 0;
  134           int seconds      = 0;
  135           int milliseconds = 0;
  136           
  137           if (Token.containsTokenWithValue(tokens, d) ) {
  138               days = (int) (durationMillis / DateUtils.MILLIS_PER_DAY);
  139               durationMillis = durationMillis - (days * DateUtils.MILLIS_PER_DAY);
  140           }
  141           if (Token.containsTokenWithValue(tokens, H) ) {
  142               hours = (int) (durationMillis / DateUtils.MILLIS_PER_HOUR);
  143               durationMillis = durationMillis - (hours * DateUtils.MILLIS_PER_HOUR);
  144           }
  145           if (Token.containsTokenWithValue(tokens, m) ) {
  146               minutes = (int) (durationMillis / DateUtils.MILLIS_PER_MINUTE);
  147               durationMillis = durationMillis - (minutes * DateUtils.MILLIS_PER_MINUTE);
  148           }
  149           if (Token.containsTokenWithValue(tokens, s) ) {
  150               seconds = (int) (durationMillis / DateUtils.MILLIS_PER_SECOND);
  151               durationMillis = durationMillis - (seconds * DateUtils.MILLIS_PER_SECOND);
  152           }
  153           if (Token.containsTokenWithValue(tokens, S) ) {
  154               milliseconds = (int) durationMillis;
  155           }
  156   
  157           return format(tokens, 0, 0, days, hours, minutes, seconds, milliseconds, padWithZeros);
  158       }
  159   
  160       /**
  161        * <p>Formats an elapsed time into a plurialization correct string.</p>
  162        * 
  163        * <p>This method formats durations using the days and lower fields of the
  164        * format pattern. Months and larger are not used.</p>
  165        * 
  166        * @param durationMillis  the elapsed time to report in milliseconds
  167        * @param suppressLeadingZeroElements  suppresses leading 0 elements
  168        * @param suppressTrailingZeroElements  suppresses trailing 0 elements
  169        * @return the formatted text in days/hours/minutes/seconds
  170        */
  171       public static String formatDurationWords(
  172           long durationMillis,
  173           boolean suppressLeadingZeroElements,
  174           boolean suppressTrailingZeroElements) {
  175   
  176           // This method is generally replacable by the format method, but 
  177           // there are a series of tweaks and special cases that require 
  178           // trickery to replicate.
  179           String duration = formatDuration(durationMillis, "d' days 'H' hours 'm' minutes 's' seconds'");
  180           if (suppressLeadingZeroElements) {
  181               // this is a temporary marker on the front. Like ^ in regexp.
  182               duration = " " + duration;
  183               String tmp = StringUtils.replaceOnce(duration, " 0 days", "");
  184               if (tmp.length() != duration.length()) {
  185                   duration = tmp;
  186                   tmp = StringUtils.replaceOnce(duration, " 0 hours", "");
  187                   if (tmp.length() != duration.length()) {
  188                       duration = tmp;
  189                       tmp = StringUtils.replaceOnce(duration, " 0 minutes", "");
  190                       duration = tmp;
  191                       if (tmp.length() != duration.length()) {
  192                           duration = StringUtils.replaceOnce(tmp, " 0 seconds", "");
  193                       }
  194                   }
  195               }
  196               if (duration.length() != 0) {
  197                   // strip the space off again
  198                   duration = duration.substring(1);
  199               }
  200           }
  201           if (suppressTrailingZeroElements) {
  202               String tmp = StringUtils.replaceOnce(duration, " 0 seconds", "");
  203               if (tmp.length() != duration.length()) {
  204                   duration = tmp;
  205                   tmp = StringUtils.replaceOnce(duration, " 0 minutes", "");
  206                   if (tmp.length() != duration.length()) {
  207                       duration = tmp;
  208                       tmp = StringUtils.replaceOnce(duration, " 0 hours", "");
  209                       if (tmp.length() != duration.length()) {
  210                           duration = StringUtils.replaceOnce(tmp, " 0 days", "");
  211                       }
  212                   }
  213               }
  214           }
  215           // handle plurals
  216           duration = " " + duration;
  217           duration = StringUtils.replaceOnce(duration, " 1 seconds", " 1 second");
  218           duration = StringUtils.replaceOnce(duration, " 1 minutes", " 1 minute");
  219           duration = StringUtils.replaceOnce(duration, " 1 hours", " 1 hour");
  220           duration = StringUtils.replaceOnce(duration, " 1 days", " 1 day");
  221           return duration.trim();
  222       }
  223   
  224       //-----------------------------------------------------------------------
  225       /**
  226        * <p>Formats the time gap as a string.</p>
  227        * 
  228        * <p>The format used is the ISO8601 period format.</p>
  229        * 
  230        * @param startMillis  the start of the duration to format
  231        * @param endMillis  the end of the duration to format
  232        * @return the time as a String
  233        */
  234       public static String formatPeriodISO(long startMillis, long endMillis) {
  235           return formatPeriod(startMillis, endMillis, ISO_EXTENDED_FORMAT_PATTERN, false, TimeZone.getDefault());
  236       }
  237   
  238       /**
  239        * <p>Formats the time gap as a string, using the specified format.
  240        * Padding the left hand side of numbers with zeroes is optional.
  241        * 
  242        * @param startMillis  the start of the duration
  243        * @param endMillis  the end of the duration
  244        * @param format  the way in which to format the duration
  245        * @return the time as a String
  246        */
  247       public static String formatPeriod(long startMillis, long endMillis, String format) {
  248           return formatPeriod(startMillis, endMillis, format, true, TimeZone.getDefault());
  249       }
  250   
  251       /**
  252        * <p>Formats the time gap as a string, using the specified format.
  253        * Padding the left hand side of numbers with zeroes is optional and 
  254        * the timezone may be specified. </p>
  255        *
  256        * <p>When calculating the difference between months/days, it chooses to 
  257        * calculate months first. So when working out the number of months and 
  258        * days between January 15th and March 10th, it choose 1 month and 
  259        * 23 days gained by choosing January->February = 1 month and then 
  260        * calculating days forwards, and not the 1 month and 26 days gained by 
  261        * choosing March -> February = 1 month and then calculating days 
  262        * backwards. </p>
  263        *
  264        * <p>For more control, the <a href="http://joda-time.sf.net/">Joda-Time</a>
  265        * library is recommended.</p>
  266        * 
  267        * @param startMillis  the start of the duration
  268        * @param endMillis  the end of the duration
  269        * @param format  the way in which to format the duration
  270        * @param padWithZeros whether to pad the left hand side of numbers with 0's
  271        * @param timezone the millis are defined in
  272        * @return the time as a String
  273        */
  274       public static String formatPeriod(long startMillis, long endMillis, String format, boolean padWithZeros, 
  275               TimeZone timezone) {
  276   
  277           // Used to optimise for differences under 28 days and 
  278           // called formatDuration(millis, format); however this did not work 
  279           // over leap years. 
  280           // TODO: Compare performance to see if anything was lost by 
  281           // losing this optimisation. 
  282           
  283           Token[] tokens = lexx(format);
  284   
  285           // timezones get funky around 0, so normalizing everything to GMT 
  286           // stops the hours being off
  287           Calendar start = Calendar.getInstance(timezone);
  288           start.setTime(new Date(startMillis));
  289           Calendar end = Calendar.getInstance(timezone);
  290           end.setTime(new Date(endMillis));
  291   
  292           // initial estimates
  293           int milliseconds = end.get(Calendar.MILLISECOND) - start.get(Calendar.MILLISECOND);
  294           int seconds = end.get(Calendar.SECOND) - start.get(Calendar.SECOND);
  295           int minutes = end.get(Calendar.MINUTE) - start.get(Calendar.MINUTE);
  296           int hours = end.get(Calendar.HOUR_OF_DAY) - start.get(Calendar.HOUR_OF_DAY);
  297           int days = end.get(Calendar.DAY_OF_MONTH) - start.get(Calendar.DAY_OF_MONTH);
  298           int months = end.get(Calendar.MONTH) - start.get(Calendar.MONTH);
  299           int years = end.get(Calendar.YEAR) - start.get(Calendar.YEAR);
  300   
  301           // each initial estimate is adjusted in case it is under 0
  302           while (milliseconds < 0) {
  303               milliseconds += 1000;
  304               seconds -= 1;
  305           }
  306           while (seconds < 0) {
  307               seconds += 60;
  308               minutes -= 1;
  309           }
  310           while (minutes < 0) {
  311               minutes += 60;
  312               hours -= 1;
  313           }
  314           while (hours < 0) {
  315               hours += 24;
  316               days -= 1;
  317           }
  318          
  319           if (Token.containsTokenWithValue(tokens, M)) {
  320               while (days < 0) {
  321                   days += start.getActualMaximum(Calendar.DAY_OF_MONTH);
  322                   months -= 1;
  323                   start.add(Calendar.MONTH, 1);
  324               }
  325   
  326               while (months < 0) {
  327                   months += 12;
  328                   years -= 1;
  329               }
  330   
  331               if (!Token.containsTokenWithValue(tokens, y) && years != 0) {
  332                   while (years != 0) {
  333                       months += 12 * years;
  334                       years = 0;
  335                   }
  336               }
  337           } else {
  338               // there are no M's in the format string
  339   
  340               if( !Token.containsTokenWithValue(tokens, y) ) {
  341                   int target = end.get(Calendar.YEAR);
  342                   if (months < 0) {
  343                       // target is end-year -1
  344                       target -= 1;
  345                   }
  346                   
  347                   while ( (start.get(Calendar.YEAR) != target)) {
  348                       days += start.getActualMaximum(Calendar.DAY_OF_YEAR) - start.get(Calendar.DAY_OF_YEAR);
  349                       
  350                       // Not sure I grok why this is needed, but the brutal tests show it is
  351                       if(start instanceof GregorianCalendar) {
  352                           if( (start.get(Calendar.MONTH) == Calendar.FEBRUARY) &&
  353                               (start.get(Calendar.DAY_OF_MONTH) == 29 ) )
  354                           {
  355                               days += 1;
  356                           }
  357                       }
  358                       
  359                       start.add(Calendar.YEAR, 1);
  360                       
  361                       days += start.get(Calendar.DAY_OF_YEAR);
  362                   }
  363                   
  364                   years = 0;
  365               }
  366               
  367               while( start.get(Calendar.MONTH) != end.get(Calendar.MONTH) ) {
  368                   days += start.getActualMaximum(Calendar.DAY_OF_MONTH);
  369                   start.add(Calendar.MONTH, 1);
  370               }
  371               
  372               months = 0;            
  373   
  374               while (days < 0) {
  375                   days += start.getActualMaximum(Calendar.DAY_OF_MONTH);
  376                   months -= 1;
  377                   start.add(Calendar.MONTH, 1);
  378               }
  379               
  380           }
  381   
  382           // The rest of this code adds in values that 
  383           // aren't requested. This allows the user to ask for the 
  384           // number of months and get the real count and not just 0->11.
  385   
  386           if (!Token.containsTokenWithValue(tokens, d)) {
  387               hours += 24 * days;
  388               days = 0;
  389           }
  390           if (!Token.containsTokenWithValue(tokens, H)) {
  391               minutes += 60 * hours;
  392               hours = 0;
  393           }
  394           if (!Token.containsTokenWithValue(tokens, m)) {
  395               seconds += 60 * minutes;
  396               minutes = 0;
  397           }
  398           if (!Token.containsTokenWithValue(tokens, s)) {
  399               milliseconds += 1000 * seconds;
  400               seconds = 0;
  401           }
  402   
  403           return format(tokens, years, months, days, hours, minutes, seconds, milliseconds, padWithZeros);
  404       }
  405   
  406       //-----------------------------------------------------------------------
  407       /**
  408        * <p>The internal method to do the formatting.</p>
  409        * 
  410        * @param tokens  the tokens
  411        * @param years  the number of years
  412        * @param months  the number of months
  413        * @param days  the number of days
  414        * @param hours  the number of hours
  415        * @param minutes  the number of minutes
  416        * @param seconds  the number of seconds
  417        * @param milliseconds  the number of millis
  418        * @param padWithZeros  whether to pad
  419        * @return the formatted string
  420        */
  421       static String format(Token[] tokens, int years, int months, int days, int hours, int minutes, int seconds,
  422               int milliseconds, boolean padWithZeros) {
  423           StringBuffer buffer = new StringBuffer();
  424           boolean lastOutputSeconds = false;
  425           int sz = tokens.length;
  426           for (int i = 0; i < sz; i++) {
  427               Token token = tokens[i];
  428               Object value = token.getValue();
  429               int count = token.getCount();
  430               if (value instanceof StringBuffer) {
  431                   buffer.append(value.toString());
  432               } else {
  433                   if (value == y) {
  434                       buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(years), count, '0') : Integer
  435                               .toString(years));
  436                       lastOutputSeconds = false;
  437                   } else if (value == M) {
  438                       buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(months), count, '0') : Integer
  439                               .toString(months));
  440                       lastOutputSeconds = false;
  441                   } else if (value == d) {
  442                       buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(days), count, '0') : Integer
  443                               .toString(days));
  444                       lastOutputSeconds = false;
  445                   } else if (value == H) {
  446                       buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(hours), count, '0') : Integer
  447                               .toString(hours));
  448                       lastOutputSeconds = false;
  449                   } else if (value == m) {
  450                       buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(minutes), count, '0') : Integer
  451                               .toString(minutes));
  452                       lastOutputSeconds = false;
  453                   } else if (value == s) {
  454                       buffer.append(padWithZeros ? StringUtils.leftPad(Integer.toString(seconds), count, '0') : Integer
  455                               .toString(seconds));
  456                       lastOutputSeconds = true;
  457                   } else if (value == S) {
  458                       if (lastOutputSeconds) {
  459                           milliseconds += 1000;
  460                           String str = padWithZeros
  461                                   ? StringUtils.leftPad(Integer.toString(milliseconds), count, '0')
  462                                   : Integer.toString(milliseconds);
  463                           buffer.append(str.substring(1));
  464                       } else {
  465                           buffer.append(padWithZeros
  466                                   ? StringUtils.leftPad(Integer.toString(milliseconds), count, '0')
  467                                   : Integer.toString(milliseconds));
  468                       }
  469                       lastOutputSeconds = false;
  470                   }
  471               }
  472           }
  473           return buffer.toString();
  474       }
  475   
  476       static final Object y = "y";
  477       static final Object M = "M";
  478       static final Object d = "d";
  479       static final Object H = "H";
  480       static final Object m = "m";
  481       static final Object s = "s";
  482       static final Object S = "S";
  483       
  484       /**
  485        * Parses a classic date format string into Tokens
  486        *
  487        * @param format to parse
  488        * @return Token[] of tokens
  489        */
  490       static Token[] lexx(String format) {
  491           char[] array = format.toCharArray();
  492           ArrayList list = new ArrayList(array.length);
  493   
  494           boolean inLiteral = false;
  495           StringBuffer buffer = null;
  496           Token previous = null;
  497           int sz = array.length;
  498           for(int i=0; i<sz; i++) {
  499               char ch = array[i];
  500               if(inLiteral && ch != '\'') {
  501                   buffer.append(ch);
  502                   continue;
  503               }
  504               Object value = null;
  505               switch(ch) {
  506                   // TODO: Need to handle escaping of '
  507                   case '\'' : 
  508                     if(inLiteral) {
  509                         buffer = null;
  510                         inLiteral = false;
  511                     } else {
  512                         buffer = new StringBuffer();
  513                         list.add(new Token(buffer));
  514                         inLiteral = true;
  515                     }
  516                     break;
  517                   case 'y'  : value = y; break;
  518                   case 'M'  : value = M; break;
  519                   case 'd'  : value = d; break;
  520                   case 'H'  : value = H; break;
  521                   case 'm'  : value = m; break;
  522                   case 's'  : value = s; break;
  523                   case 'S'  : value = S; break;
  524                   default   : 
  525                     if(buffer == null) {
  526                         buffer = new StringBuffer();
  527                         list.add(new Token(buffer));
  528                     }
  529                     buffer.append(ch);
  530               }
  531   
  532               if(value != null) {
  533                   if(previous != null && previous.getValue() == value) {
  534                       previous.increment();
  535                   } else {
  536                       Token token = new Token(value);
  537                       list.add(token); 
  538                       previous = token;
  539                   }
  540                   buffer = null; 
  541               }
  542           }
  543           return (Token[]) list.toArray( new Token[list.size()] );
  544       }
  545   
  546       /**
  547        * Element that is parsed from the format pattern.
  548        */
  549       static class Token {
  550   
  551           /**
  552            * Helper method to determine if a set of tokens contain a value
  553            *
  554            * @param tokens set to look in
  555            * @param value to look for
  556            * @return boolean <code>true</code> if contained
  557            */
  558           static boolean containsTokenWithValue(Token[] tokens, Object value) {
  559               int sz = tokens.length;
  560               for (int i = 0; i < sz; i++) {
  561                   if (tokens[i].getValue() == value) {
  562                       return true;
  563                   }
  564               }
  565               return false;
  566           }
  567   
  568           private Object value;
  569           private int count;
  570   
  571           /**
  572            * Wraps a token around a value. A value would be something like a 'Y'.
  573            *
  574            * @param value to wrap
  575            */
  576           Token(Object value) {
  577               this.value = value;
  578               this.count = 1;
  579           }
  580   
  581           /**
  582            * Wraps a token around a repeated number of a value, for example it would 
  583            * store 'yyyy' as a value for y and a count of 4.
  584            *
  585            * @param value to wrap
  586            * @param count to wrap
  587            */
  588           Token(Object value, int count) {
  589               this.value = value;
  590               this.count = count;
  591           }
  592   
  593           /**
  594            * Adds another one of the value
  595            */
  596           void increment() { 
  597               count++;
  598           }
  599   
  600           /**
  601            * Gets the current number of values represented
  602            *
  603            * @return int number of values represented
  604            */
  605           int getCount() {
  606               return count;
  607           }
  608   
  609           /**
  610            * Gets the particular value this token represents.
  611            * 
  612            * @return Object value
  613            */
  614           Object getValue() {
  615               return value;
  616           }
  617   
  618           /**
  619            * Supports equality of this Token to another Token.
  620            *
  621            * @param obj2 Object to consider equality of
  622            * @return boolean <code>true</code> if equal
  623            */
  624           public boolean equals(Object obj2) {
  625               if (obj2 instanceof Token) {
  626                   Token tok2 = (Token) obj2;
  627                   if (this.value.getClass() != tok2.value.getClass()) {
  628                       return false;
  629                   }
  630                   if (this.count != tok2.count) {
  631                       return false;
  632                   }
  633                   if (this.value instanceof StringBuffer) {
  634                       return this.value.toString().equals(tok2.value.toString());
  635                   } else if (this.value instanceof Number) {
  636                       return this.value.equals(tok2.value);
  637                   } else {
  638                       return this.value == tok2.value;
  639                   }
  640               }
  641               return false;
  642           }
  643   
  644           /**
  645            * Returns a hashcode for the token equal to the 
  646            * hashcode for the token's value. Thus 'TT' and 'TTTT' 
  647            * will have the same hashcode. 
  648            *
  649            * @return The hashcode for the token
  650            */
  651           public int hashCode() {
  652               return this.value.hashCode();
  653           }
  654   
  655           /**
  656            * Represents this token as a String.
  657            *
  658            * @return String representation of the token
  659            */
  660           public String toString() {
  661               return StringUtils.repeat(this.value.toString(), this.count);
  662           }
  663       }
  664   
  665   }

Save This Page
Home » commons-lang-2.4-src » org.apache.commons » lang » time » [javadoc | source]