Source Code Cross Referenced for SerialDate.java in  » Graphic-Library » jcommon-components » org » jfree » date » 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 » Graphic Library » jcommon components » org.jfree.date 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* ========================================================================
0002:         * JCommon : a free general purpose class library for the Java(tm) platform
0003:         * ========================================================================
0004:         *
0005:         * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
0006:         * 
0007:         * Project Info:  http://www.jfree.org/jcommon/index.html
0008:         *
0009:         * This library is free software; you can redistribute it and/or modify it 
0010:         * under the terms of the GNU Lesser General Public License as published by 
0011:         * the Free Software Foundation; either version 2.1 of the License, or 
0012:         * (at your option) any later version.
0013:         *
0014:         * This library is distributed in the hope that it will be useful, but 
0015:         * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
0016:         * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
0017:         * License for more details.
0018:         *
0019:         * You should have received a copy of the GNU Lesser General Public
0020:         * License along with this library; if not, write to the Free Software
0021:         * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
0022:         * USA.  
0023:         *
0024:         * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
0025:         * in the United States and other countries.]
0026:         *
0027:         * ---------------
0028:         * SerialDate.java
0029:         * ---------------
0030:         * (C) Copyright 2001-2006, by Object Refinery Limited.
0031:         *
0032:         * Original Author:  David Gilbert (for Object Refinery Limited);
0033:         * Contributor(s):   -;
0034:         *
0035:         * $Id: SerialDate.java,v 1.8 2006/08/29 13:44:16 mungady Exp $
0036:         *
0037:         * Changes (from 11-Oct-2001)
0038:         * --------------------------
0039:         * 11-Oct-2001 : Re-organised the class and moved it to new package 
0040:         *               com.jrefinery.date (DG);
0041:         * 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate 
0042:         *               class (DG);
0043:         * 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate 
0044:         *               class is gone (DG);  Changed getPreviousDayOfWeek(), 
0045:         *               getFollowingDayOfWeek() and getNearestDayOfWeek() to correct 
0046:         *               bugs (DG);
0047:         * 05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG);
0048:         * 29-May-2002 : Moved the month constants into a separate interface 
0049:         *               (MonthConstants) (DG);
0050:         * 27-Aug-2002 : Fixed bug in addMonths() method, thanks to N???levka Petr (DG);
0051:         * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
0052:         * 13-Mar-2003 : Implemented Serializable (DG);
0053:         * 29-May-2003 : Fixed bug in addMonths method (DG);
0054:         * 04-Sep-2003 : Implemented Comparable.  Updated the isInRange javadocs (DG);
0055:         * 05-Jan-2005 : Fixed bug in addYears() method (1096282) (DG);
0056:         * 
0057:         */
0058:
0059:        package org.jfree.date;
0060:
0061:        import java.io.Serializable;
0062:        import java.text.DateFormatSymbols;
0063:        import java.text.SimpleDateFormat;
0064:        import java.util.Calendar;
0065:        import java.util.GregorianCalendar;
0066:
0067:        /**
0068:         *  An abstract class that defines our requirements for manipulating dates,
0069:         *  without tying down a particular implementation.
0070:         *  <P>
0071:         *  Requirement 1 : match at least what Excel does for dates;
0072:         *  Requirement 2 : the date represented by the class is immutable;
0073:         *  <P>
0074:         *  Why not just use java.util.Date?  We will, when it makes sense.  At times,
0075:         *  java.util.Date can be *too* precise - it represents an instant in time,
0076:         *  accurate to 1/1000th of a second (with the date itself depending on the
0077:         *  time-zone).  Sometimes we just want to represent a particular day (e.g. 21
0078:         *  January 2015) without concerning ourselves about the time of day, or the
0079:         *  time-zone, or anything else.  That's what we've defined SerialDate for.
0080:         *  <P>
0081:         *  You can call getInstance() to get a concrete subclass of SerialDate,
0082:         *  without worrying about the exact implementation.
0083:         *
0084:         * @author David Gilbert
0085:         */
0086:        public abstract class SerialDate implements  Comparable, Serializable,
0087:                MonthConstants {
0088:
0089:            /** For serialization. */
0090:            private static final long serialVersionUID = -293716040467423637L;
0091:
0092:            /** Date format symbols. */
0093:            public static final DateFormatSymbols DATE_FORMAT_SYMBOLS = new SimpleDateFormat()
0094:                    .getDateFormatSymbols();
0095:
0096:            /** The serial number for 1 January 1900. */
0097:            public static final int SERIAL_LOWER_BOUND = 2;
0098:
0099:            /** The serial number for 31 December 9999. */
0100:            public static final int SERIAL_UPPER_BOUND = 2958465;
0101:
0102:            /** The lowest year value supported by this date format. */
0103:            public static final int MINIMUM_YEAR_SUPPORTED = 1900;
0104:
0105:            /** The highest year value supported by this date format. */
0106:            public static final int MAXIMUM_YEAR_SUPPORTED = 9999;
0107:
0108:            /** Useful constant for Monday. Equivalent to java.util.Calendar.MONDAY. */
0109:            public static final int MONDAY = Calendar.MONDAY;
0110:
0111:            /** 
0112:             * Useful constant for Tuesday. Equivalent to java.util.Calendar.TUESDAY. 
0113:             */
0114:            public static final int TUESDAY = Calendar.TUESDAY;
0115:
0116:            /** 
0117:             * Useful constant for Wednesday. Equivalent to 
0118:             * java.util.Calendar.WEDNESDAY. 
0119:             */
0120:            public static final int WEDNESDAY = Calendar.WEDNESDAY;
0121:
0122:            /** 
0123:             * Useful constant for Thrusday. Equivalent to java.util.Calendar.THURSDAY. 
0124:             */
0125:            public static final int THURSDAY = Calendar.THURSDAY;
0126:
0127:            /** Useful constant for Friday. Equivalent to java.util.Calendar.FRIDAY. */
0128:            public static final int FRIDAY = Calendar.FRIDAY;
0129:
0130:            /** 
0131:             * Useful constant for Saturday. Equivalent to java.util.Calendar.SATURDAY.
0132:             */
0133:            public static final int SATURDAY = Calendar.SATURDAY;
0134:
0135:            /** Useful constant for Sunday. Equivalent to java.util.Calendar.SUNDAY. */
0136:            public static final int SUNDAY = Calendar.SUNDAY;
0137:
0138:            /** The number of days in each month in non leap years. */
0139:            static final int[] LAST_DAY_OF_MONTH = { 0, 31, 28, 31, 30, 31, 30,
0140:                    31, 31, 30, 31, 30, 31 };
0141:
0142:            /** The number of days in a (non-leap) year up to the end of each month. */
0143:            static final int[] AGGREGATE_DAYS_TO_END_OF_MONTH = { 0, 31, 59,
0144:                    90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
0145:
0146:            /** The number of days in a year up to the end of the preceding month. */
0147:            static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = { 0,
0148:                    0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 };
0149:
0150:            /** The number of days in a leap year up to the end of each month. */
0151:            static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_MONTH = { 0,
0152:                    31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 };
0153:
0154:            /** 
0155:             * The number of days in a leap year up to the end of the preceding month. 
0156:             */
0157:            static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH = {
0158:                    0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335,
0159:                    366 };
0160:
0161:            /** A useful constant for referring to the first week in a month. */
0162:            public static final int FIRST_WEEK_IN_MONTH = 1;
0163:
0164:            /** A useful constant for referring to the second week in a month. */
0165:            public static final int SECOND_WEEK_IN_MONTH = 2;
0166:
0167:            /** A useful constant for referring to the third week in a month. */
0168:            public static final int THIRD_WEEK_IN_MONTH = 3;
0169:
0170:            /** A useful constant for referring to the fourth week in a month. */
0171:            public static final int FOURTH_WEEK_IN_MONTH = 4;
0172:
0173:            /** A useful constant for referring to the last week in a month. */
0174:            public static final int LAST_WEEK_IN_MONTH = 0;
0175:
0176:            /** Useful range constant. */
0177:            public static final int INCLUDE_NONE = 0;
0178:
0179:            /** Useful range constant. */
0180:            public static final int INCLUDE_FIRST = 1;
0181:
0182:            /** Useful range constant. */
0183:            public static final int INCLUDE_SECOND = 2;
0184:
0185:            /** Useful range constant. */
0186:            public static final int INCLUDE_BOTH = 3;
0187:
0188:            /** 
0189:             * Useful constant for specifying a day of the week relative to a fixed 
0190:             * date. 
0191:             */
0192:            public static final int PRECEDING = -1;
0193:
0194:            /** 
0195:             * Useful constant for specifying a day of the week relative to a fixed 
0196:             * date. 
0197:             */
0198:            public static final int NEAREST = 0;
0199:
0200:            /** 
0201:             * Useful constant for specifying a day of the week relative to a fixed 
0202:             * date. 
0203:             */
0204:            public static final int FOLLOWING = 1;
0205:
0206:            /** A description for the date. */
0207:            private String description;
0208:
0209:            /**
0210:             * Default constructor.
0211:             */
0212:            protected SerialDate() {
0213:            }
0214:
0215:            /**
0216:             * Returns <code>true</code> if the supplied integer code represents a 
0217:             * valid day-of-the-week, and <code>false</code> otherwise.
0218:             *
0219:             * @param code  the code being checked for validity.
0220:             *
0221:             * @return <code>true</code> if the supplied integer code represents a 
0222:             *         valid day-of-the-week, and <code>false</code> otherwise.
0223:             */
0224:            public static boolean isValidWeekdayCode(final int code) {
0225:
0226:                switch (code) {
0227:                case SUNDAY:
0228:                case MONDAY:
0229:                case TUESDAY:
0230:                case WEDNESDAY:
0231:                case THURSDAY:
0232:                case FRIDAY:
0233:                case SATURDAY:
0234:                    return true;
0235:                default:
0236:                    return false;
0237:                }
0238:
0239:            }
0240:
0241:            /**
0242:             * Converts the supplied string to a day of the week.
0243:             *
0244:             * @param s  a string representing the day of the week.
0245:             *
0246:             * @return <code>-1</code> if the string is not convertable, the day of 
0247:             *         the week otherwise.
0248:             */
0249:            public static int stringToWeekdayCode(String s) {
0250:
0251:                final String[] shortWeekdayNames = DATE_FORMAT_SYMBOLS
0252:                        .getShortWeekdays();
0253:                final String[] weekDayNames = DATE_FORMAT_SYMBOLS.getWeekdays();
0254:
0255:                int result = -1;
0256:                s = s.trim();
0257:                for (int i = 0; i < weekDayNames.length; i++) {
0258:                    if (s.equals(shortWeekdayNames[i])) {
0259:                        result = i;
0260:                        break;
0261:                    }
0262:                    if (s.equals(weekDayNames[i])) {
0263:                        result = i;
0264:                        break;
0265:                    }
0266:                }
0267:                return result;
0268:
0269:            }
0270:
0271:            /**
0272:             * Returns a string representing the supplied day-of-the-week.
0273:             * <P>
0274:             * Need to find a better approach.
0275:             *
0276:             * @param weekday  the day of the week.
0277:             *
0278:             * @return a string representing the supplied day-of-the-week.
0279:             */
0280:            public static String weekdayCodeToString(final int weekday) {
0281:
0282:                final String[] weekdays = DATE_FORMAT_SYMBOLS.getWeekdays();
0283:                return weekdays[weekday];
0284:
0285:            }
0286:
0287:            /**
0288:             * Returns an array of month names.
0289:             *
0290:             * @return an array of month names.
0291:             */
0292:            public static String[] getMonths() {
0293:
0294:                return getMonths(false);
0295:
0296:            }
0297:
0298:            /**
0299:             * Returns an array of month names.
0300:             *
0301:             * @param shortened  a flag indicating that shortened month names should 
0302:             *                   be returned.
0303:             *
0304:             * @return an array of month names.
0305:             */
0306:            public static String[] getMonths(final boolean shortened) {
0307:
0308:                if (shortened) {
0309:                    return DATE_FORMAT_SYMBOLS.getShortMonths();
0310:                } else {
0311:                    return DATE_FORMAT_SYMBOLS.getMonths();
0312:                }
0313:
0314:            }
0315:
0316:            /**
0317:             * Returns true if the supplied integer code represents a valid month.
0318:             *
0319:             * @param code  the code being checked for validity.
0320:             *
0321:             * @return <code>true</code> if the supplied integer code represents a 
0322:             *         valid month.
0323:             */
0324:            public static boolean isValidMonthCode(final int code) {
0325:
0326:                switch (code) {
0327:                case JANUARY:
0328:                case FEBRUARY:
0329:                case MARCH:
0330:                case APRIL:
0331:                case MAY:
0332:                case JUNE:
0333:                case JULY:
0334:                case AUGUST:
0335:                case SEPTEMBER:
0336:                case OCTOBER:
0337:                case NOVEMBER:
0338:                case DECEMBER:
0339:                    return true;
0340:                default:
0341:                    return false;
0342:                }
0343:
0344:            }
0345:
0346:            /**
0347:             * Returns the quarter for the specified month.
0348:             *
0349:             * @param code  the month code (1-12).
0350:             *
0351:             * @return the quarter that the month belongs to.
0352:             */
0353:            public static int monthCodeToQuarter(final int code) {
0354:
0355:                switch (code) {
0356:                case JANUARY:
0357:                case FEBRUARY:
0358:                case MARCH:
0359:                    return 1;
0360:                case APRIL:
0361:                case MAY:
0362:                case JUNE:
0363:                    return 2;
0364:                case JULY:
0365:                case AUGUST:
0366:                case SEPTEMBER:
0367:                    return 3;
0368:                case OCTOBER:
0369:                case NOVEMBER:
0370:                case DECEMBER:
0371:                    return 4;
0372:                default:
0373:                    throw new IllegalArgumentException(
0374:                            "SerialDate.monthCodeToQuarter: invalid month code.");
0375:                }
0376:
0377:            }
0378:
0379:            /**
0380:             * Returns a string representing the supplied month.
0381:             * <P>
0382:             * The string returned is the long form of the month name taken from the 
0383:             * default locale.
0384:             *
0385:             * @param month  the month.
0386:             *
0387:             * @return a string representing the supplied month.
0388:             */
0389:            public static String monthCodeToString(final int month) {
0390:
0391:                return monthCodeToString(month, false);
0392:
0393:            }
0394:
0395:            /**
0396:             * Returns a string representing the supplied month.
0397:             * <P>
0398:             * The string returned is the long or short form of the month name taken 
0399:             * from the default locale.
0400:             *
0401:             * @param month  the month.
0402:             * @param shortened  if <code>true</code> return the abbreviation of the 
0403:             *                   month.
0404:             *
0405:             * @return a string representing the supplied month.
0406:             */
0407:            public static String monthCodeToString(final int month,
0408:                    final boolean shortened) {
0409:
0410:                // check arguments...
0411:                if (!isValidMonthCode(month)) {
0412:                    throw new IllegalArgumentException(
0413:                            "SerialDate.monthCodeToString: month outside valid range.");
0414:                }
0415:
0416:                final String[] months;
0417:
0418:                if (shortened) {
0419:                    months = DATE_FORMAT_SYMBOLS.getShortMonths();
0420:                } else {
0421:                    months = DATE_FORMAT_SYMBOLS.getMonths();
0422:                }
0423:
0424:                return months[month - 1];
0425:
0426:            }
0427:
0428:            /**
0429:             * Converts a string to a month code.
0430:             * <P>
0431:             * This method will return one of the constants JANUARY, FEBRUARY, ..., 
0432:             * DECEMBER that corresponds to the string.  If the string is not 
0433:             * recognised, this method returns -1.
0434:             *
0435:             * @param s  the string to parse.
0436:             *
0437:             * @return <code>-1</code> if the string is not parseable, the month of the
0438:             *         year otherwise.
0439:             */
0440:            public static int stringToMonthCode(String s) {
0441:
0442:                final String[] shortMonthNames = DATE_FORMAT_SYMBOLS
0443:                        .getShortMonths();
0444:                final String[] monthNames = DATE_FORMAT_SYMBOLS.getMonths();
0445:
0446:                int result = -1;
0447:                s = s.trim();
0448:
0449:                // first try parsing the string as an integer (1-12)...
0450:                try {
0451:                    result = Integer.parseInt(s);
0452:                } catch (NumberFormatException e) {
0453:                    // suppress
0454:                }
0455:
0456:                // now search through the month names...
0457:                if ((result < 1) || (result > 12)) {
0458:                    for (int i = 0; i < monthNames.length; i++) {
0459:                        if (s.equals(shortMonthNames[i])) {
0460:                            result = i + 1;
0461:                            break;
0462:                        }
0463:                        if (s.equals(monthNames[i])) {
0464:                            result = i + 1;
0465:                            break;
0466:                        }
0467:                    }
0468:                }
0469:
0470:                return result;
0471:
0472:            }
0473:
0474:            /**
0475:             * Returns true if the supplied integer code represents a valid 
0476:             * week-in-the-month, and false otherwise.
0477:             *
0478:             * @param code  the code being checked for validity.
0479:             * @return <code>true</code> if the supplied integer code represents a 
0480:             *         valid week-in-the-month.
0481:             */
0482:            public static boolean isValidWeekInMonthCode(final int code) {
0483:
0484:                switch (code) {
0485:                case FIRST_WEEK_IN_MONTH:
0486:                case SECOND_WEEK_IN_MONTH:
0487:                case THIRD_WEEK_IN_MONTH:
0488:                case FOURTH_WEEK_IN_MONTH:
0489:                case LAST_WEEK_IN_MONTH:
0490:                    return true;
0491:                default:
0492:                    return false;
0493:                }
0494:
0495:            }
0496:
0497:            /**
0498:             * Determines whether or not the specified year is a leap year.
0499:             *
0500:             * @param yyyy  the year (in the range 1900 to 9999).
0501:             *
0502:             * @return <code>true</code> if the specified year is a leap year.
0503:             */
0504:            public static boolean isLeapYear(final int yyyy) {
0505:
0506:                if ((yyyy % 4) != 0) {
0507:                    return false;
0508:                } else if ((yyyy % 400) == 0) {
0509:                    return true;
0510:                } else if ((yyyy % 100) == 0) {
0511:                    return false;
0512:                } else {
0513:                    return true;
0514:                }
0515:
0516:            }
0517:
0518:            /**
0519:             * Returns the number of leap years from 1900 to the specified year 
0520:             * INCLUSIVE.
0521:             * <P>
0522:             * Note that 1900 is not a leap year.
0523:             *
0524:             * @param yyyy  the year (in the range 1900 to 9999).
0525:             *
0526:             * @return the number of leap years from 1900 to the specified year.
0527:             */
0528:            public static int leapYearCount(final int yyyy) {
0529:
0530:                final int leap4 = (yyyy - 1896) / 4;
0531:                final int leap100 = (yyyy - 1800) / 100;
0532:                final int leap400 = (yyyy - 1600) / 400;
0533:                return leap4 - leap100 + leap400;
0534:
0535:            }
0536:
0537:            /**
0538:             * Returns the number of the last day of the month, taking into account 
0539:             * leap years.
0540:             *
0541:             * @param month  the month.
0542:             * @param yyyy  the year (in the range 1900 to 9999).
0543:             *
0544:             * @return the number of the last day of the month.
0545:             */
0546:            public static int lastDayOfMonth(final int month, final int yyyy) {
0547:
0548:                final int result = LAST_DAY_OF_MONTH[month];
0549:                if (month != FEBRUARY) {
0550:                    return result;
0551:                } else if (isLeapYear(yyyy)) {
0552:                    return result + 1;
0553:                } else {
0554:                    return result;
0555:                }
0556:
0557:            }
0558:
0559:            /**
0560:             * Creates a new date by adding the specified number of days to the base 
0561:             * date.
0562:             *
0563:             * @param days  the number of days to add (can be negative).
0564:             * @param base  the base date.
0565:             *
0566:             * @return a new date.
0567:             */
0568:            public static SerialDate addDays(final int days,
0569:                    final SerialDate base) {
0570:
0571:                final int serialDayNumber = base.toSerial() + days;
0572:                return SerialDate.createInstance(serialDayNumber);
0573:
0574:            }
0575:
0576:            /**
0577:             * Creates a new date by adding the specified number of months to the base 
0578:             * date.
0579:             * <P>
0580:             * If the base date is close to the end of the month, the day on the result
0581:             * may be adjusted slightly:  31 May + 1 month = 30 June.
0582:             *
0583:             * @param months  the number of months to add (can be negative).
0584:             * @param base  the base date.
0585:             *
0586:             * @return a new date.
0587:             */
0588:            public static SerialDate addMonths(final int months,
0589:                    final SerialDate base) {
0590:
0591:                final int yy = (12 * base.getYYYY() + base.getMonth() + months - 1) / 12;
0592:                final int mm = (12 * base.getYYYY() + base.getMonth() + months - 1) % 12 + 1;
0593:                final int dd = Math.min(base.getDayOfMonth(), SerialDate
0594:                        .lastDayOfMonth(mm, yy));
0595:                return SerialDate.createInstance(dd, mm, yy);
0596:
0597:            }
0598:
0599:            /**
0600:             * Creates a new date by adding the specified number of years to the base 
0601:             * date.
0602:             *
0603:             * @param years  the number of years to add (can be negative).
0604:             * @param base  the base date.
0605:             *
0606:             * @return A new date.
0607:             */
0608:            public static SerialDate addYears(final int years,
0609:                    final SerialDate base) {
0610:
0611:                final int baseY = base.getYYYY();
0612:                final int baseM = base.getMonth();
0613:                final int baseD = base.getDayOfMonth();
0614:
0615:                final int targetY = baseY + years;
0616:                final int targetD = Math.min(baseD, SerialDate.lastDayOfMonth(
0617:                        baseM, targetY));
0618:
0619:                return SerialDate.createInstance(targetD, baseM, targetY);
0620:
0621:            }
0622:
0623:            /**
0624:             * Returns the latest date that falls on the specified day-of-the-week and 
0625:             * is BEFORE the base date.
0626:             *
0627:             * @param targetWeekday  a code for the target day-of-the-week.
0628:             * @param base  the base date.
0629:             *
0630:             * @return the latest date that falls on the specified day-of-the-week and 
0631:             *         is BEFORE the base date.
0632:             */
0633:            public static SerialDate getPreviousDayOfWeek(
0634:                    final int targetWeekday, final SerialDate base) {
0635:
0636:                // check arguments...
0637:                if (!SerialDate.isValidWeekdayCode(targetWeekday)) {
0638:                    throw new IllegalArgumentException(
0639:                            "Invalid day-of-the-week code.");
0640:                }
0641:
0642:                // find the date...
0643:                final int adjust;
0644:                final int baseDOW = base.getDayOfWeek();
0645:                if (baseDOW > targetWeekday) {
0646:                    adjust = Math.min(0, targetWeekday - baseDOW);
0647:                } else {
0648:                    adjust = -7 + Math.max(0, targetWeekday - baseDOW);
0649:                }
0650:
0651:                return SerialDate.addDays(adjust, base);
0652:
0653:            }
0654:
0655:            /**
0656:             * Returns the earliest date that falls on the specified day-of-the-week
0657:             * and is AFTER the base date.
0658:             *
0659:             * @param targetWeekday  a code for the target day-of-the-week.
0660:             * @param base  the base date.
0661:             *
0662:             * @return the earliest date that falls on the specified day-of-the-week 
0663:             *         and is AFTER the base date.
0664:             */
0665:            public static SerialDate getFollowingDayOfWeek(
0666:                    final int targetWeekday, final SerialDate base) {
0667:
0668:                // check arguments...
0669:                if (!SerialDate.isValidWeekdayCode(targetWeekday)) {
0670:                    throw new IllegalArgumentException(
0671:                            "Invalid day-of-the-week code.");
0672:                }
0673:
0674:                // find the date...
0675:                final int adjust;
0676:                final int baseDOW = base.getDayOfWeek();
0677:                if (baseDOW > targetWeekday) {
0678:                    adjust = 7 + Math.min(0, targetWeekday - baseDOW);
0679:                } else {
0680:                    adjust = Math.max(0, targetWeekday - baseDOW);
0681:                }
0682:
0683:                return SerialDate.addDays(adjust, base);
0684:            }
0685:
0686:            /**
0687:             * Returns the date that falls on the specified day-of-the-week and is
0688:             * CLOSEST to the base date.
0689:             *
0690:             * @param targetDOW  a code for the target day-of-the-week.
0691:             * @param base  the base date.
0692:             *
0693:             * @return the date that falls on the specified day-of-the-week and is 
0694:             *         CLOSEST to the base date.
0695:             */
0696:            public static SerialDate getNearestDayOfWeek(final int targetDOW,
0697:                    final SerialDate base) {
0698:
0699:                // check arguments...
0700:                if (!SerialDate.isValidWeekdayCode(targetDOW)) {
0701:                    throw new IllegalArgumentException(
0702:                            "Invalid day-of-the-week code.");
0703:                }
0704:
0705:                // find the date...
0706:                final int baseDOW = base.getDayOfWeek();
0707:                int adjust = -Math.abs(targetDOW - baseDOW);
0708:                if (adjust >= 4) {
0709:                    adjust = 7 - adjust;
0710:                }
0711:                if (adjust <= -4) {
0712:                    adjust = 7 + adjust;
0713:                }
0714:                return SerialDate.addDays(adjust, base);
0715:
0716:            }
0717:
0718:            /**
0719:             * Rolls the date forward to the last day of the month.
0720:             *
0721:             * @param base  the base date.
0722:             *
0723:             * @return a new serial date.
0724:             */
0725:            public SerialDate getEndOfCurrentMonth(final SerialDate base) {
0726:                final int last = SerialDate.lastDayOfMonth(base.getMonth(),
0727:                        base.getYYYY());
0728:                return SerialDate.createInstance(last, base.getMonth(), base
0729:                        .getYYYY());
0730:            }
0731:
0732:            /**
0733:             * Returns a string corresponding to the week-in-the-month code.
0734:             * <P>
0735:             * Need to find a better approach.
0736:             *
0737:             * @param count  an integer code representing the week-in-the-month.
0738:             *
0739:             * @return a string corresponding to the week-in-the-month code.
0740:             */
0741:            public static String weekInMonthToString(final int count) {
0742:
0743:                switch (count) {
0744:                case SerialDate.FIRST_WEEK_IN_MONTH:
0745:                    return "First";
0746:                case SerialDate.SECOND_WEEK_IN_MONTH:
0747:                    return "Second";
0748:                case SerialDate.THIRD_WEEK_IN_MONTH:
0749:                    return "Third";
0750:                case SerialDate.FOURTH_WEEK_IN_MONTH:
0751:                    return "Fourth";
0752:                case SerialDate.LAST_WEEK_IN_MONTH:
0753:                    return "Last";
0754:                default:
0755:                    return "SerialDate.weekInMonthToString(): invalid code.";
0756:                }
0757:
0758:            }
0759:
0760:            /**
0761:             * Returns a string representing the supplied 'relative'.
0762:             * <P>
0763:             * Need to find a better approach.
0764:             *
0765:             * @param relative  a constant representing the 'relative'.
0766:             *
0767:             * @return a string representing the supplied 'relative'.
0768:             */
0769:            public static String relativeToString(final int relative) {
0770:
0771:                switch (relative) {
0772:                case SerialDate.PRECEDING:
0773:                    return "Preceding";
0774:                case SerialDate.NEAREST:
0775:                    return "Nearest";
0776:                case SerialDate.FOLLOWING:
0777:                    return "Following";
0778:                default:
0779:                    return "ERROR : Relative To String";
0780:                }
0781:
0782:            }
0783:
0784:            /**
0785:             * Factory method that returns an instance of some concrete subclass of 
0786:             * {@link SerialDate}.
0787:             *
0788:             * @param day  the day (1-31).
0789:             * @param month  the month (1-12).
0790:             * @param yyyy  the year (in the range 1900 to 9999).
0791:             *
0792:             * @return An instance of {@link SerialDate}.
0793:             */
0794:            public static SerialDate createInstance(final int day,
0795:                    final int month, final int yyyy) {
0796:                return new SpreadsheetDate(day, month, yyyy);
0797:            }
0798:
0799:            /**
0800:             * Factory method that returns an instance of some concrete subclass of 
0801:             * {@link SerialDate}.
0802:             *
0803:             * @param serial  the serial number for the day (1 January 1900 = 2).
0804:             *
0805:             * @return a instance of SerialDate.
0806:             */
0807:            public static SerialDate createInstance(final int serial) {
0808:                return new SpreadsheetDate(serial);
0809:            }
0810:
0811:            /**
0812:             * Factory method that returns an instance of a subclass of SerialDate.
0813:             *
0814:             * @param date  A Java date object.
0815:             *
0816:             * @return a instance of SerialDate.
0817:             */
0818:            public static SerialDate createInstance(final java.util.Date date) {
0819:
0820:                final GregorianCalendar calendar = new GregorianCalendar();
0821:                calendar.setTime(date);
0822:                return new SpreadsheetDate(calendar.get(Calendar.DATE),
0823:                        calendar.get(Calendar.MONTH) + 1, calendar
0824:                                .get(Calendar.YEAR));
0825:
0826:            }
0827:
0828:            /**
0829:             * Returns the serial number for the date, where 1 January 1900 = 2 (this
0830:             * corresponds, almost, to the numbering system used in Microsoft Excel for
0831:             * Windows and Lotus 1-2-3).
0832:             *
0833:             * @return the serial number for the date.
0834:             */
0835:            public abstract int toSerial();
0836:
0837:            /**
0838:             * Returns a java.util.Date.  Since java.util.Date has more precision than
0839:             * SerialDate, we need to define a convention for the 'time of day'.
0840:             *
0841:             * @return this as <code>java.util.Date</code>.
0842:             */
0843:            public abstract java.util.Date toDate();
0844:
0845:            /**
0846:             * Returns the description that is attached to the date.  It is not 
0847:             * required that a date have a description, but for some applications it 
0848:             * is useful.
0849:             *
0850:             * @return The description (possibly <code>null</code>).
0851:             */
0852:            public String getDescription() {
0853:                return this .description;
0854:            }
0855:
0856:            /**
0857:             * Sets the description for the date.
0858:             *
0859:             * @param description  the description for this date (<code>null</code> 
0860:             *                     permitted).
0861:             */
0862:            public void setDescription(final String description) {
0863:                this .description = description;
0864:            }
0865:
0866:            /**
0867:             * Converts the date to a string.
0868:             *
0869:             * @return  a string representation of the date.
0870:             */
0871:            public String toString() {
0872:                return getDayOfMonth() + "-"
0873:                        + SerialDate.monthCodeToString(getMonth()) + "-"
0874:                        + getYYYY();
0875:            }
0876:
0877:            /**
0878:             * Returns the year (assume a valid range of 1900 to 9999).
0879:             *
0880:             * @return the year.
0881:             */
0882:            public abstract int getYYYY();
0883:
0884:            /**
0885:             * Returns the month (January = 1, February = 2, March = 3).
0886:             *
0887:             * @return the month of the year.
0888:             */
0889:            public abstract int getMonth();
0890:
0891:            /**
0892:             * Returns the day of the month.
0893:             *
0894:             * @return the day of the month.
0895:             */
0896:            public abstract int getDayOfMonth();
0897:
0898:            /**
0899:             * Returns the day of the week.
0900:             *
0901:             * @return the day of the week.
0902:             */
0903:            public abstract int getDayOfWeek();
0904:
0905:            /**
0906:             * Returns the difference (in days) between this date and the specified 
0907:             * 'other' date.
0908:             * <P>
0909:             * The result is positive if this date is after the 'other' date and
0910:             * negative if it is before the 'other' date.
0911:             *
0912:             * @param other  the date being compared to.
0913:             *
0914:             * @return the difference between this and the other date.
0915:             */
0916:            public abstract int compare(SerialDate other);
0917:
0918:            /**
0919:             * Returns true if this SerialDate represents the same date as the 
0920:             * specified SerialDate.
0921:             *
0922:             * @param other  the date being compared to.
0923:             *
0924:             * @return <code>true</code> if this SerialDate represents the same date as 
0925:             *         the specified SerialDate.
0926:             */
0927:            public abstract boolean isOn(SerialDate other);
0928:
0929:            /**
0930:             * Returns true if this SerialDate represents an earlier date compared to
0931:             * the specified SerialDate.
0932:             *
0933:             * @param other  The date being compared to.
0934:             *
0935:             * @return <code>true</code> if this SerialDate represents an earlier date 
0936:             *         compared to the specified SerialDate.
0937:             */
0938:            public abstract boolean isBefore(SerialDate other);
0939:
0940:            /**
0941:             * Returns true if this SerialDate represents the same date as the 
0942:             * specified SerialDate.
0943:             *
0944:             * @param other  the date being compared to.
0945:             *
0946:             * @return <code>true<code> if this SerialDate represents the same date
0947:             *         as the specified SerialDate.
0948:             */
0949:            public abstract boolean isOnOrBefore(SerialDate other);
0950:
0951:            /**
0952:             * Returns true if this SerialDate represents the same date as the 
0953:             * specified SerialDate.
0954:             *
0955:             * @param other  the date being compared to.
0956:             *
0957:             * @return <code>true</code> if this SerialDate represents the same date
0958:             *         as the specified SerialDate.
0959:             */
0960:            public abstract boolean isAfter(SerialDate other);
0961:
0962:            /**
0963:             * Returns true if this SerialDate represents the same date as the 
0964:             * specified SerialDate.
0965:             *
0966:             * @param other  the date being compared to.
0967:             *
0968:             * @return <code>true</code> if this SerialDate represents the same date
0969:             *         as the specified SerialDate.
0970:             */
0971:            public abstract boolean isOnOrAfter(SerialDate other);
0972:
0973:            /**
0974:             * Returns <code>true</code> if this {@link SerialDate} is within the 
0975:             * specified range (INCLUSIVE).  The date order of d1 and d2 is not 
0976:             * important.
0977:             *
0978:             * @param d1  a boundary date for the range.
0979:             * @param d2  the other boundary date for the range.
0980:             *
0981:             * @return A boolean.
0982:             */
0983:            public abstract boolean isInRange(SerialDate d1, SerialDate d2);
0984:
0985:            /**
0986:             * Returns <code>true</code> if this {@link SerialDate} is within the 
0987:             * specified range (caller specifies whether or not the end-points are 
0988:             * included).  The date order of d1 and d2 is not important.
0989:             *
0990:             * @param d1  a boundary date for the range.
0991:             * @param d2  the other boundary date for the range.
0992:             * @param include  a code that controls whether or not the start and end 
0993:             *                 dates are included in the range.
0994:             *
0995:             * @return A boolean.
0996:             */
0997:            public abstract boolean isInRange(SerialDate d1, SerialDate d2,
0998:                    int include);
0999:
1000:            /**
1001:             * Returns the latest date that falls on the specified day-of-the-week and
1002:             * is BEFORE this date.
1003:             *
1004:             * @param targetDOW  a code for the target day-of-the-week.
1005:             *
1006:             * @return the latest date that falls on the specified day-of-the-week and
1007:             *         is BEFORE this date.
1008:             */
1009:            public SerialDate getPreviousDayOfWeek(final int targetDOW) {
1010:                return getPreviousDayOfWeek(targetDOW, this );
1011:            }
1012:
1013:            /**
1014:             * Returns the earliest date that falls on the specified day-of-the-week
1015:             * and is AFTER this date.
1016:             *
1017:             * @param targetDOW  a code for the target day-of-the-week.
1018:             *
1019:             * @return the earliest date that falls on the specified day-of-the-week
1020:             *         and is AFTER this date.
1021:             */
1022:            public SerialDate getFollowingDayOfWeek(final int targetDOW) {
1023:                return getFollowingDayOfWeek(targetDOW, this );
1024:            }
1025:
1026:            /**
1027:             * Returns the nearest date that falls on the specified day-of-the-week.
1028:             *
1029:             * @param targetDOW  a code for the target day-of-the-week.
1030:             *
1031:             * @return the nearest date that falls on the specified day-of-the-week.
1032:             */
1033:            public SerialDate getNearestDayOfWeek(final int targetDOW) {
1034:                return getNearestDayOfWeek(targetDOW, this);
1035:            }
1036:
1037:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.