Home » jcommon-1.0.13 » org.jfree.date » [javadoc | source]

    1   /* ========================================================================
    2    * JCommon : a free general purpose class library for the Java(tm) platform
    3    * ========================================================================
    4    *
    5    * (C) Copyright 2000-2006, by Object Refinery Limited and Contributors.
    6    * 
    7    * Project Info:  http://www.jfree.org/jcommon/index.html
    8    *
    9    * This library is free software; you can redistribute it and/or modify it 
   10    * under the terms of the GNU Lesser General Public License as published by 
   11    * the Free Software Foundation; either version 2.1 of the License, or 
   12    * (at your option) any later version.
   13    *
   14    * This library is distributed in the hope that it will be useful, but 
   15    * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
   16    * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public 
   17    * License for more details.
   18    *
   19    * You should have received a copy of the GNU Lesser General Public
   20    * License along with this library; if not, write to the Free Software
   21    * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, 
   22    * USA.  
   23    *
   24    * [Java is a trademark or registered trademark of Sun Microsystems, Inc. 
   25    * in the United States and other countries.]
   26    *
   27    * ---------------
   28    * SerialDate.java
   29    * ---------------
   30    * (C) Copyright 2001-2006, by Object Refinery Limited.
   31    *
   32    * Original Author:  David Gilbert (for Object Refinery Limited);
   33    * Contributor(s):   -;
   34    *
   35    * $Id: SerialDate.java,v 1.8 2006/08/29 13:44:16 mungady Exp $
   36    *
   37    * Changes (from 11-Oct-2001)
   38    * --------------------------
   39    * 11-Oct-2001 : Re-organised the class and moved it to new package 
   40    *               com.jrefinery.date (DG);
   41    * 05-Nov-2001 : Added a getDescription() method, and eliminated NotableDate 
   42    *               class (DG);
   43    * 12-Nov-2001 : IBD requires setDescription() method, now that NotableDate 
   44    *               class is gone (DG);  Changed getPreviousDayOfWeek(), 
   45    *               getFollowingDayOfWeek() and getNearestDayOfWeek() to correct 
   46    *               bugs (DG);
   47    * 05-Dec-2001 : Fixed bug in SpreadsheetDate class (DG);
   48    * 29-May-2002 : Moved the month constants into a separate interface 
   49    *               (MonthConstants) (DG);
   50    * 27-Aug-2002 : Fixed bug in addMonths() method, thanks to N???levka Petr (DG);
   51    * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
   52    * 13-Mar-2003 : Implemented Serializable (DG);
   53    * 29-May-2003 : Fixed bug in addMonths method (DG);
   54    * 04-Sep-2003 : Implemented Comparable.  Updated the isInRange javadocs (DG);
   55    * 05-Jan-2005 : Fixed bug in addYears() method (1096282) (DG);
   56    * 
   57    */
   58   
   59   package org.jfree.date;
   60   
   61   import java.io.Serializable;
   62   import java.text.DateFormatSymbols;
   63   import java.text.SimpleDateFormat;
   64   import java.util.Calendar;
   65   import java.util.GregorianCalendar;
   66   
   67   /**
   68    *  An abstract class that defines our requirements for manipulating dates,
   69    *  without tying down a particular implementation.
   70    *  <P>
   71    *  Requirement 1 : match at least what Excel does for dates;
   72    *  Requirement 2 : the date represented by the class is immutable;
   73    *  <P>
   74    *  Why not just use java.util.Date?  We will, when it makes sense.  At times,
   75    *  java.util.Date can be *too* precise - it represents an instant in time,
   76    *  accurate to 1/1000th of a second (with the date itself depending on the
   77    *  time-zone).  Sometimes we just want to represent a particular day (e.g. 21
   78    *  January 2015) without concerning ourselves about the time of day, or the
   79    *  time-zone, or anything else.  That's what we've defined SerialDate for.
   80    *  <P>
   81    *  You can call getInstance() to get a concrete subclass of SerialDate,
   82    *  without worrying about the exact implementation.
   83    *
   84    * @author David Gilbert
   85    */
   86   public abstract class SerialDate implements Comparable, 
   87                                               Serializable, 
   88                                               MonthConstants {
   89   
   90       /** For serialization. */
   91       private static final long serialVersionUID = -293716040467423637L;
   92       
   93       /** Date format symbols. */
   94       public static final DateFormatSymbols
   95           DATE_FORMAT_SYMBOLS = new SimpleDateFormat().getDateFormatSymbols();
   96   
   97       /** The serial number for 1 January 1900. */
   98       public static final int SERIAL_LOWER_BOUND = 2;
   99   
  100       /** The serial number for 31 December 9999. */
  101       public static final int SERIAL_UPPER_BOUND = 2958465;
  102   
  103       /** The lowest year value supported by this date format. */
  104       public static final int MINIMUM_YEAR_SUPPORTED = 1900;
  105   
  106       /** The highest year value supported by this date format. */
  107       public static final int MAXIMUM_YEAR_SUPPORTED = 9999;
  108   
  109       /** Useful constant for Monday. Equivalent to java.util.Calendar.MONDAY. */
  110       public static final int MONDAY = Calendar.MONDAY;
  111   
  112       /** 
  113        * Useful constant for Tuesday. Equivalent to java.util.Calendar.TUESDAY. 
  114        */
  115       public static final int TUESDAY = Calendar.TUESDAY;
  116   
  117       /** 
  118        * Useful constant for Wednesday. Equivalent to 
  119        * java.util.Calendar.WEDNESDAY. 
  120        */
  121       public static final int WEDNESDAY = Calendar.WEDNESDAY;
  122   
  123       /** 
  124        * Useful constant for Thrusday. Equivalent to java.util.Calendar.THURSDAY. 
  125        */
  126       public static final int THURSDAY = Calendar.THURSDAY;
  127   
  128       /** Useful constant for Friday. Equivalent to java.util.Calendar.FRIDAY. */
  129       public static final int FRIDAY = Calendar.FRIDAY;
  130   
  131       /** 
  132        * Useful constant for Saturday. Equivalent to java.util.Calendar.SATURDAY.
  133        */
  134       public static final int SATURDAY = Calendar.SATURDAY;
  135   
  136       /** Useful constant for Sunday. Equivalent to java.util.Calendar.SUNDAY. */
  137       public static final int SUNDAY = Calendar.SUNDAY;
  138   
  139       /** The number of days in each month in non leap years. */
  140       static final int[] LAST_DAY_OF_MONTH =
  141           {0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
  142   
  143       /** The number of days in a (non-leap) year up to the end of each month. */
  144       static final int[] AGGREGATE_DAYS_TO_END_OF_MONTH =
  145           {0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
  146   
  147       /** The number of days in a year up to the end of the preceding month. */
  148       static final int[] AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH =
  149           {0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365};
  150   
  151       /** The number of days in a leap year up to the end of each month. */
  152       static final int[] LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_MONTH =
  153           {0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
  154   
  155       /** 
  156        * The number of days in a leap year up to the end of the preceding month. 
  157        */
  158       static final int[] 
  159           LEAP_YEAR_AGGREGATE_DAYS_TO_END_OF_PRECEDING_MONTH =
  160               {0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366};
  161   
  162       /** A useful constant for referring to the first week in a month. */
  163       public static final int FIRST_WEEK_IN_MONTH = 1;
  164   
  165       /** A useful constant for referring to the second week in a month. */
  166       public static final int SECOND_WEEK_IN_MONTH = 2;
  167   
  168       /** A useful constant for referring to the third week in a month. */
  169       public static final int THIRD_WEEK_IN_MONTH = 3;
  170   
  171       /** A useful constant for referring to the fourth week in a month. */
  172       public static final int FOURTH_WEEK_IN_MONTH = 4;
  173   
  174       /** A useful constant for referring to the last week in a month. */
  175       public static final int LAST_WEEK_IN_MONTH = 0;
  176   
  177       /** Useful range constant. */
  178       public static final int INCLUDE_NONE = 0;
  179   
  180       /** Useful range constant. */
  181       public static final int INCLUDE_FIRST = 1;
  182   
  183       /** Useful range constant. */
  184       public static final int INCLUDE_SECOND = 2;
  185   
  186       /** Useful range constant. */
  187       public static final int INCLUDE_BOTH = 3;
  188   
  189       /** 
  190        * Useful constant for specifying a day of the week relative to a fixed 
  191        * date. 
  192        */
  193       public static final int PRECEDING = -1;
  194   
  195       /** 
  196        * Useful constant for specifying a day of the week relative to a fixed 
  197        * date. 
  198        */
  199       public static final int NEAREST = 0;
  200   
  201       /** 
  202        * Useful constant for specifying a day of the week relative to a fixed 
  203        * date. 
  204        */
  205       public static final int FOLLOWING = 1;
  206   
  207       /** A description for the date. */
  208       private String description;
  209   
  210       /**
  211        * Default constructor.
  212        */
  213       protected SerialDate() {
  214       }
  215   
  216       /**
  217        * Returns <code>true</code> if the supplied integer code represents a 
  218        * valid day-of-the-week, and <code>false</code> otherwise.
  219        *
  220        * @param code  the code being checked for validity.
  221        *
  222        * @return <code>true</code> if the supplied integer code represents a 
  223        *         valid day-of-the-week, and <code>false</code> otherwise.
  224        */
  225       public static boolean isValidWeekdayCode(final int code) {
  226   
  227           switch(code) {
  228               case SUNDAY: 
  229               case MONDAY: 
  230               case TUESDAY: 
  231               case WEDNESDAY: 
  232               case THURSDAY: 
  233               case FRIDAY: 
  234               case SATURDAY: 
  235                   return true;
  236               default: 
  237                   return false;
  238           }
  239   
  240       }
  241   
  242       /**
  243        * Converts the supplied string to a day of the week.
  244        *
  245        * @param s  a string representing the day of the week.
  246        *
  247        * @return <code>-1</code> if the string is not convertable, the day of 
  248        *         the week otherwise.
  249        */
  250       public static int stringToWeekdayCode(String s) {
  251   
  252           final String[] shortWeekdayNames 
  253               = DATE_FORMAT_SYMBOLS.getShortWeekdays();
  254           final String[] weekDayNames = DATE_FORMAT_SYMBOLS.getWeekdays();
  255   
  256           int result = -1;
  257           s = s.trim();
  258           for (int i = 0; i < weekDayNames.length; i++) {
  259               if (s.equals(shortWeekdayNames[i])) {
  260                   result = i;
  261                   break;
  262               }
  263               if (s.equals(weekDayNames[i])) {
  264                   result = i;
  265                   break;
  266               }
  267           }
  268           return result;
  269   
  270       }
  271   
  272       /**
  273        * Returns a string representing the supplied day-of-the-week.
  274        * <P>
  275        * Need to find a better approach.
  276        *
  277        * @param weekday  the day of the week.
  278        *
  279        * @return a string representing the supplied day-of-the-week.
  280        */
  281       public static String weekdayCodeToString(final int weekday) {
  282   
  283           final String[] weekdays = DATE_FORMAT_SYMBOLS.getWeekdays();
  284           return weekdays[weekday];
  285   
  286       }
  287   
  288       /**
  289        * Returns an array of month names.
  290        *
  291        * @return an array of month names.
  292        */
  293       public static String[] getMonths() {
  294   
  295           return getMonths(false);
  296   
  297       }
  298   
  299       /**
  300        * Returns an array of month names.
  301        *
  302        * @param shortened  a flag indicating that shortened month names should 
  303        *                   be returned.
  304        *
  305        * @return an array of month names.
  306        */
  307       public static String[] getMonths(final boolean shortened) {
  308   
  309           if (shortened) {
  310               return DATE_FORMAT_SYMBOLS.getShortMonths();
  311           }
  312           else {
  313               return DATE_FORMAT_SYMBOLS.getMonths();
  314           }
  315   
  316       }
  317   
  318       /**
  319        * Returns true if the supplied integer code represents a valid month.
  320        *
  321        * @param code  the code being checked for validity.
  322        *
  323        * @return <code>true</code> if the supplied integer code represents a 
  324        *         valid month.
  325        */
  326       public static boolean isValidMonthCode(final int code) {
  327   
  328           switch(code) {
  329               case JANUARY: 
  330               case FEBRUARY: 
  331               case MARCH: 
  332               case APRIL: 
  333               case MAY: 
  334               case JUNE: 
  335               case JULY: 
  336               case AUGUST: 
  337               case SEPTEMBER: 
  338               case OCTOBER: 
  339               case NOVEMBER: 
  340               case DECEMBER: 
  341                   return true;
  342               default: 
  343                   return false;
  344           }
  345   
  346       }
  347   
  348       /**
  349        * Returns the quarter for the specified month.
  350        *
  351        * @param code  the month code (1-12).
  352        *
  353        * @return the quarter that the month belongs to.
  354        */
  355       public static int monthCodeToQuarter(final int code) {
  356   
  357           switch(code) {
  358               case JANUARY: 
  359               case FEBRUARY: 
  360               case MARCH: return 1;
  361               case APRIL: 
  362               case MAY: 
  363               case JUNE: return 2;
  364               case JULY: 
  365               case AUGUST: 
  366               case SEPTEMBER: return 3;
  367               case OCTOBER: 
  368               case NOVEMBER: 
  369               case DECEMBER: return 4;
  370               default: throw new IllegalArgumentException(
  371                   "SerialDate.monthCodeToQuarter: invalid month code.");
  372           }
  373   
  374       }
  375   
  376       /**
  377        * Returns a string representing the supplied month.
  378        * <P>
  379        * The string returned is the long form of the month name taken from the 
  380        * default locale.
  381        *
  382        * @param month  the month.
  383        *
  384        * @return a string representing the supplied month.
  385        */
  386       public static String monthCodeToString(final int month) {
  387   
  388           return monthCodeToString(month, false);
  389   
  390       }
  391   
  392       /**
  393        * Returns a string representing the supplied month.
  394        * <P>
  395        * The string returned is the long or short form of the month name taken 
  396        * from the default locale.
  397        *
  398        * @param month  the month.
  399        * @param shortened  if <code>true</code> return the abbreviation of the 
  400        *                   month.
  401        *
  402        * @return a string representing the supplied month.
  403        */
  404       public static String monthCodeToString(final int month, 
  405                                              final boolean shortened) {
  406   
  407           // check arguments...
  408           if (!isValidMonthCode(month)) {
  409               throw new IllegalArgumentException(
  410                   "SerialDate.monthCodeToString: month outside valid range.");
  411           }
  412   
  413           final String[] months;
  414   
  415           if (shortened) {
  416               months = DATE_FORMAT_SYMBOLS.getShortMonths();
  417           }
  418           else {
  419               months = DATE_FORMAT_SYMBOLS.getMonths();
  420           }
  421   
  422           return months[month - 1];
  423   
  424       }
  425   
  426       /**
  427        * Converts a string to a month code.
  428        * <P>
  429        * This method will return one of the constants JANUARY, FEBRUARY, ..., 
  430        * DECEMBER that corresponds to the string.  If the string is not 
  431        * recognised, this method returns -1.
  432        *
  433        * @param s  the string to parse.
  434        *
  435        * @return <code>-1</code> if the string is not parseable, the month of the
  436        *         year otherwise.
  437        */
  438       public static int stringToMonthCode(String s) {
  439   
  440           final String[] shortMonthNames = DATE_FORMAT_SYMBOLS.getShortMonths();
  441           final String[] monthNames = DATE_FORMAT_SYMBOLS.getMonths();
  442   
  443           int result = -1;
  444           s = s.trim();
  445   
  446           // first try parsing the string as an integer (1-12)...
  447           try {
  448               result = Integer.parseInt(s);
  449           }
  450           catch (NumberFormatException e) {
  451               // suppress
  452           }
  453   
  454           // now search through the month names...
  455           if ((result < 1) || (result > 12)) {
  456               for (int i = 0; i < monthNames.length; i++) {
  457                   if (s.equals(shortMonthNames[i])) {
  458                       result = i + 1;
  459                       break;
  460                   }
  461                   if (s.equals(monthNames[i])) {
  462                       result = i + 1;
  463                       break;
  464                   }
  465               }
  466           }
  467   
  468           return result;
  469   
  470       }
  471   
  472       /**
  473        * Returns true if the supplied integer code represents a valid 
  474        * week-in-the-month, and false otherwise.
  475        *
  476        * @param code  the code being checked for validity.
  477        * @return <code>true</code> if the supplied integer code represents a 
  478        *         valid week-in-the-month.
  479        */
  480       public static boolean isValidWeekInMonthCode(final int code) {
  481   
  482           switch(code) {
  483               case FIRST_WEEK_IN_MONTH: 
  484               case SECOND_WEEK_IN_MONTH: 
  485               case THIRD_WEEK_IN_MONTH: 
  486               case FOURTH_WEEK_IN_MONTH: 
  487               case LAST_WEEK_IN_MONTH: return true;
  488               default: return false;
  489           }
  490   
  491       }
  492   
  493       /**
  494        * Determines whether or not the specified year is a leap year.
  495        *
  496        * @param yyyy  the year (in the range 1900 to 9999).
  497        *
  498        * @return <code>true</code> if the specified year is a leap year.
  499        */
  500       public static boolean isLeapYear(final int yyyy) {
  501   
  502           if ((yyyy % 4) != 0) {
  503               return false;
  504           }
  505           else if ((yyyy % 400) == 0) {
  506               return true;
  507           }
  508           else if ((yyyy % 100) == 0) {
  509               return false;
  510           }
  511           else {
  512               return true;
  513           }
  514   
  515       }
  516   
  517       /**
  518        * Returns the number of leap years from 1900 to the specified year 
  519        * INCLUSIVE.
  520        * <P>
  521        * Note that 1900 is not a leap year.
  522        *
  523        * @param yyyy  the year (in the range 1900 to 9999).
  524        *
  525        * @return the number of leap years from 1900 to the specified year.
  526        */
  527       public static int leapYearCount(final int yyyy) {
  528   
  529           final int leap4 = (yyyy - 1896) / 4;
  530           final int leap100 = (yyyy - 1800) / 100;
  531           final int leap400 = (yyyy - 1600) / 400;
  532           return leap4 - leap100 + leap400;
  533   
  534       }
  535   
  536       /**
  537        * Returns the number of the last day of the month, taking into account 
  538        * leap years.
  539        *
  540        * @param month  the month.
  541        * @param yyyy  the year (in the range 1900 to 9999).
  542        *
  543        * @return the number of the last day of the month.
  544        */
  545       public static int lastDayOfMonth(final int month, final int yyyy) {
  546   
  547           final int result = LAST_DAY_OF_MONTH[month];
  548           if (month != FEBRUARY) {
  549               return result;
  550           }
  551           else if (isLeapYear(yyyy)) {
  552               return result + 1;
  553           }
  554           else {
  555               return result;
  556           }
  557   
  558       }
  559   
  560       /**
  561        * Creates a new date by adding the specified number of days to the base 
  562        * date.
  563        *
  564        * @param days  the number of days to add (can be negative).
  565        * @param base  the base date.
  566        *
  567        * @return a new date.
  568        */
  569       public static SerialDate addDays(final int days, final SerialDate base) {
  570   
  571           final int serialDayNumber = base.toSerial() + days;
  572           return SerialDate.createInstance(serialDayNumber);
  573   
  574       }
  575   
  576       /**
  577        * Creates a new date by adding the specified number of months to the base 
  578        * date.
  579        * <P>
  580        * If the base date is close to the end of the month, the day on the result
  581        * may be adjusted slightly:  31 May + 1 month = 30 June.
  582        *
  583        * @param months  the number of months to add (can be negative).
  584        * @param base  the base date.
  585        *
  586        * @return a new date.
  587        */
  588       public static SerialDate addMonths(final int months, 
  589                                          final SerialDate base) {
  590   
  591           final int yy = (12 * base.getYYYY() + base.getMonth() + months - 1) 
  592                          / 12;
  593           final int mm = (12 * base.getYYYY() + base.getMonth() + months - 1) 
  594                          % 12 + 1;
  595           final int dd = Math.min(
  596               base.getDayOfMonth(), SerialDate.lastDayOfMonth(mm, yy)
  597           );
  598           return SerialDate.createInstance(dd, mm, yy);
  599   
  600       }
  601   
  602       /**
  603        * Creates a new date by adding the specified number of years to the base 
  604        * date.
  605        *
  606        * @param years  the number of years to add (can be negative).
  607        * @param base  the base date.
  608        *
  609        * @return A new date.
  610        */
  611       public static SerialDate addYears(final int years, final SerialDate base) {
  612   
  613           final int baseY = base.getYYYY();
  614           final int baseM = base.getMonth();
  615           final int baseD = base.getDayOfMonth();
  616   
  617           final int targetY = baseY + years;
  618           final int targetD = Math.min(
  619               baseD, SerialDate.lastDayOfMonth(baseM, targetY)
  620           );
  621   
  622           return SerialDate.createInstance(targetD, baseM, targetY);
  623   
  624       }
  625   
  626       /**
  627        * Returns the latest date that falls on the specified day-of-the-week and 
  628        * is BEFORE the base date.
  629        *
  630        * @param targetWeekday  a code for the target day-of-the-week.
  631        * @param base  the base date.
  632        *
  633        * @return the latest date that falls on the specified day-of-the-week and 
  634        *         is BEFORE the base date.
  635        */
  636       public static SerialDate getPreviousDayOfWeek(final int targetWeekday, 
  637                                                     final SerialDate base) {
  638   
  639           // check arguments...
  640           if (!SerialDate.isValidWeekdayCode(targetWeekday)) {
  641               throw new IllegalArgumentException(
  642                   "Invalid day-of-the-week code."
  643               );
  644           }
  645   
  646           // find the date...
  647           final int adjust;
  648           final int baseDOW = base.getDayOfWeek();
  649           if (baseDOW > targetWeekday) {
  650               adjust = Math.min(0, targetWeekday - baseDOW);
  651           }
  652           else {
  653               adjust = -7 + Math.max(0, targetWeekday - baseDOW);
  654           }
  655   
  656           return SerialDate.addDays(adjust, base);
  657   
  658       }
  659   
  660       /**
  661        * Returns the earliest date that falls on the specified day-of-the-week
  662        * and is AFTER the base date.
  663        *
  664        * @param targetWeekday  a code for the target day-of-the-week.
  665        * @param base  the base date.
  666        *
  667        * @return the earliest date that falls on the specified day-of-the-week 
  668        *         and is AFTER the base date.
  669        */
  670       public static SerialDate getFollowingDayOfWeek(final int targetWeekday, 
  671                                                      final SerialDate base) {
  672   
  673           // check arguments...
  674           if (!SerialDate.isValidWeekdayCode(targetWeekday)) {
  675               throw new IllegalArgumentException(
  676                   "Invalid day-of-the-week code."
  677               );
  678           }
  679   
  680           // find the date...
  681           final int adjust;
  682           final int baseDOW = base.getDayOfWeek();
  683           if (baseDOW > targetWeekday) {
  684               adjust = 7 + Math.min(0, targetWeekday - baseDOW);
  685           }
  686           else {
  687               adjust = Math.max(0, targetWeekday - baseDOW);
  688           }
  689   
  690           return SerialDate.addDays(adjust, base);
  691       }
  692   
  693       /**
  694        * Returns the date that falls on the specified day-of-the-week and is
  695        * CLOSEST to the base date.
  696        *
  697        * @param targetDOW  a code for the target day-of-the-week.
  698        * @param base  the base date.
  699        *
  700        * @return the date that falls on the specified day-of-the-week and is 
  701        *         CLOSEST to the base date.
  702        */
  703       public static SerialDate getNearestDayOfWeek(final int targetDOW,  
  704                                                    final SerialDate base) {
  705   
  706           // check arguments...
  707           if (!SerialDate.isValidWeekdayCode(targetDOW)) {
  708               throw new IllegalArgumentException(
  709                   "Invalid day-of-the-week code."
  710               );
  711           }
  712   
  713           // find the date...
  714           final int baseDOW = base.getDayOfWeek();
  715           int adjust = -Math.abs(targetDOW - baseDOW);
  716           if (adjust >= 4) {
  717               adjust = 7 - adjust;
  718           }
  719           if (adjust <= -4) {
  720               adjust = 7 + adjust;
  721           }
  722           return SerialDate.addDays(adjust, base);
  723   
  724       }
  725   
  726       /**
  727        * Rolls the date forward to the last day of the month.
  728        *
  729        * @param base  the base date.
  730        *
  731        * @return a new serial date.
  732        */
  733       public SerialDate getEndOfCurrentMonth(final SerialDate base) {
  734           final int last = SerialDate.lastDayOfMonth(
  735               base.getMonth(), base.getYYYY()
  736           );
  737           return SerialDate.createInstance(last, base.getMonth(), base.getYYYY());
  738       }
  739   
  740       /**
  741        * Returns a string corresponding to the week-in-the-month code.
  742        * <P>
  743        * Need to find a better approach.
  744        *
  745        * @param count  an integer code representing the week-in-the-month.
  746        *
  747        * @return a string corresponding to the week-in-the-month code.
  748        */
  749       public static String weekInMonthToString(final int count) {
  750   
  751           switch (count) {
  752               case SerialDate.FIRST_WEEK_IN_MONTH : return "First";
  753               case SerialDate.SECOND_WEEK_IN_MONTH : return "Second";
  754               case SerialDate.THIRD_WEEK_IN_MONTH : return "Third";
  755               case SerialDate.FOURTH_WEEK_IN_MONTH : return "Fourth";
  756               case SerialDate.LAST_WEEK_IN_MONTH : return "Last";
  757               default :
  758                   return "SerialDate.weekInMonthToString(): invalid code.";
  759           }
  760   
  761       }
  762   
  763       /**
  764        * Returns a string representing the supplied 'relative'.
  765        * <P>
  766        * Need to find a better approach.
  767        *
  768        * @param relative  a constant representing the 'relative'.
  769        *
  770        * @return a string representing the supplied 'relative'.
  771        */
  772       public static String relativeToString(final int relative) {
  773   
  774           switch (relative) {
  775               case SerialDate.PRECEDING : return "Preceding";
  776               case SerialDate.NEAREST : return "Nearest";
  777               case SerialDate.FOLLOWING : return "Following";
  778               default : return "ERROR : Relative To String";
  779           }
  780   
  781       }
  782   
  783       /**
  784        * Factory method that returns an instance of some concrete subclass of 
  785        * {@link SerialDate}.
  786        *
  787        * @param day  the day (1-31).
  788        * @param month  the month (1-12).
  789        * @param yyyy  the year (in the range 1900 to 9999).
  790        *
  791        * @return An instance of {@link SerialDate}.
  792        */
  793       public static SerialDate createInstance(final int day, final int month, 
  794                                               final int yyyy) {
  795           return new SpreadsheetDate(day, month, yyyy);
  796       }
  797   
  798       /**
  799        * Factory method that returns an instance of some concrete subclass of 
  800        * {@link SerialDate}.
  801        *
  802        * @param serial  the serial number for the day (1 January 1900 = 2).
  803        *
  804        * @return a instance of SerialDate.
  805        */
  806       public static SerialDate createInstance(final int serial) {
  807           return new SpreadsheetDate(serial);
  808       }
  809   
  810       /**
  811        * Factory method that returns an instance of a subclass of SerialDate.
  812        *
  813        * @param date  A Java date object.
  814        *
  815        * @return a instance of SerialDate.
  816        */
  817       public static SerialDate createInstance(final java.util.Date date) {
  818   
  819           final GregorianCalendar calendar = new GregorianCalendar();
  820           calendar.setTime(date);
  821           return new SpreadsheetDate(calendar.get(Calendar.DATE),
  822                                      calendar.get(Calendar.MONTH) + 1,
  823                                      calendar.get(Calendar.YEAR));
  824   
  825       }
  826   
  827       /**
  828        * Returns the serial number for the date, where 1 January 1900 = 2 (this
  829        * corresponds, almost, to the numbering system used in Microsoft Excel for
  830        * Windows and Lotus 1-2-3).
  831        *
  832        * @return the serial number for the date.
  833        */
  834       public abstract int toSerial();
  835   
  836       /**
  837        * Returns a java.util.Date.  Since java.util.Date has more precision than
  838        * SerialDate, we need to define a convention for the 'time of day'.
  839        *
  840        * @return this as <code>java.util.Date</code>.
  841        */
  842       public abstract java.util.Date toDate();
  843   
  844       /**
  845        * Returns the description that is attached to the date.  It is not 
  846        * required that a date have a description, but for some applications it 
  847        * is useful.
  848        *
  849        * @return The description (possibly <code>null</code>).
  850        */
  851       public String getDescription() {
  852           return this.description;
  853       }
  854   
  855       /**
  856        * Sets the description for the date.
  857        *
  858        * @param description  the description for this date (<code>null</code> 
  859        *                     permitted).
  860        */
  861       public void setDescription(final String description) {
  862           this.description = description;
  863       }
  864   
  865       /**
  866        * Converts the date to a string.
  867        *
  868        * @return  a string representation of the date.
  869        */
  870       public String toString() {
  871           return getDayOfMonth() + "-" + SerialDate.monthCodeToString(getMonth())
  872                                  + "-" + getYYYY();
  873       }
  874   
  875       /**
  876        * Returns the year (assume a valid range of 1900 to 9999).
  877        *
  878        * @return the year.
  879        */
  880       public abstract int getYYYY();
  881   
  882       /**
  883        * Returns the month (January = 1, February = 2, March = 3).
  884        *
  885        * @return the month of the year.
  886        */
  887       public abstract int getMonth();
  888   
  889       /**
  890        * Returns the day of the month.
  891        *
  892        * @return the day of the month.
  893        */
  894       public abstract int getDayOfMonth();
  895   
  896       /**
  897        * Returns the day of the week.
  898        *
  899        * @return the day of the week.
  900        */
  901       public abstract int getDayOfWeek();
  902   
  903       /**
  904        * Returns the difference (in days) between this date and the specified 
  905        * 'other' date.
  906        * <P>
  907        * The result is positive if this date is after the 'other' date and
  908        * negative if it is before the 'other' date.
  909        *
  910        * @param other  the date being compared to.
  911        *
  912        * @return the difference between this and the other date.
  913        */
  914       public abstract int compare(SerialDate other);
  915   
  916       /**
  917        * Returns true if this SerialDate represents the same date as the 
  918        * specified SerialDate.
  919        *
  920        * @param other  the date being compared to.
  921        *
  922        * @return <code>true</code> if this SerialDate represents the same date as 
  923        *         the specified SerialDate.
  924        */
  925       public abstract boolean isOn(SerialDate other);
  926   
  927       /**
  928        * Returns true if this SerialDate represents an earlier date compared to
  929        * the specified SerialDate.
  930        *
  931        * @param other  The date being compared to.
  932        *
  933        * @return <code>true</code> if this SerialDate represents an earlier date 
  934        *         compared to the specified SerialDate.
  935        */
  936       public abstract boolean isBefore(SerialDate other);
  937   
  938       /**
  939        * Returns true if this SerialDate represents the same date as the 
  940        * specified SerialDate.
  941        *
  942        * @param other  the date being compared to.
  943        *
  944        * @return <code>true<code> if this SerialDate represents the same date
  945        *         as the specified SerialDate.
  946        */
  947       public abstract boolean isOnOrBefore(SerialDate other);
  948   
  949       /**
  950        * Returns true if this SerialDate represents the same date as the 
  951        * specified SerialDate.
  952        *
  953        * @param other  the date being compared to.
  954        *
  955        * @return <code>true</code> if this SerialDate represents the same date
  956        *         as the specified SerialDate.
  957        */
  958       public abstract boolean isAfter(SerialDate other);
  959   
  960       /**
  961        * Returns true if this SerialDate represents the same date as the 
  962        * specified SerialDate.
  963        *
  964        * @param other  the date being compared to.
  965        *
  966        * @return <code>true</code> if this SerialDate represents the same date
  967        *         as the specified SerialDate.
  968        */
  969       public abstract boolean isOnOrAfter(SerialDate other);
  970   
  971       /**
  972        * Returns <code>true</code> if this {@link SerialDate} is within the 
  973        * specified range (INCLUSIVE).  The date order of d1 and d2 is not 
  974        * important.
  975        *
  976        * @param d1  a boundary date for the range.
  977        * @param d2  the other boundary date for the range.
  978        *
  979        * @return A boolean.
  980        */
  981       public abstract boolean isInRange(SerialDate d1, SerialDate d2);
  982   
  983       /**
  984        * Returns <code>true</code> if this {@link SerialDate} is within the 
  985        * specified range (caller specifies whether or not the end-points are 
  986        * included).  The date order of d1 and d2 is not important.
  987        *
  988        * @param d1  a boundary date for the range.
  989        * @param d2  the other boundary date for the range.
  990        * @param include  a code that controls whether or not the start and end 
  991        *                 dates are included in the range.
  992        *
  993        * @return A boolean.
  994        */
  995       public abstract boolean isInRange(SerialDate d1, SerialDate d2, 
  996                                         int include);
  997   
  998       /**
  999        * Returns the latest date that falls on the specified day-of-the-week and
 1000        * is BEFORE this date.
 1001        *
 1002        * @param targetDOW  a code for the target day-of-the-week.
 1003        *
 1004        * @return the latest date that falls on the specified day-of-the-week and
 1005        *         is BEFORE this date.
 1006        */
 1007       public SerialDate getPreviousDayOfWeek(final int targetDOW) {
 1008           return getPreviousDayOfWeek(targetDOW, this);
 1009       }
 1010   
 1011       /**
 1012        * Returns the earliest date that falls on the specified day-of-the-week
 1013        * and is AFTER this date.
 1014        *
 1015        * @param targetDOW  a code for the target day-of-the-week.
 1016        *
 1017        * @return the earliest date that falls on the specified day-of-the-week
 1018        *         and is AFTER this date.
 1019        */
 1020       public SerialDate getFollowingDayOfWeek(final int targetDOW) {
 1021           return getFollowingDayOfWeek(targetDOW, this);
 1022       }
 1023   
 1024       /**
 1025        * Returns the nearest date that falls on the specified day-of-the-week.
 1026        *
 1027        * @param targetDOW  a code for the target day-of-the-week.
 1028        *
 1029        * @return the nearest date that falls on the specified day-of-the-week.
 1030        */
 1031       public SerialDate getNearestDayOfWeek(final int targetDOW) {
 1032           return getNearestDayOfWeek(targetDOW, this);
 1033       }
 1034   
 1035   }

Home » jcommon-1.0.13 » org.jfree.date » [javadoc | source]