Source Code Cross Referenced for DurationFormatUtils.java in  » Library » Apache-common-lang » org » apache » commons » lang » time » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Library » Apache common lang » org.apache.commons.lang.time 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


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