/lib/jCommon-1.0.16/source/org/jfree/date/SerialDateUtilities.java
Java | 388 lines | 190 code | 26 blank | 172 comment | 55 complexity | 5556d78070b2052f2468eb1589bfe155 MD5 | raw file
- /* ========================================================================
- * JCommon : a free general purpose class library for the Java(tm) platform
- * ========================================================================
- *
- * (C) Copyright 2000-2005, by Object Refinery Limited and Contributors.
- *
- * Project Info: http://www.jfree.org/jcommon/index.html
- *
- * This library is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation; either version 2.1 of the License, or
- * (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful, but
- * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
- * License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
- * USA.
- *
- * [Java is a trademark or registered trademark of Sun Microsystems, Inc.
- * in the United States and other countries.]
- *
- * ------------------------
- * SerialDateUtilities.java
- * ------------------------
- * (C) Copyright 2001-2003, by Object Refinery Limited.
- *
- * Original Author: David Gilbert (for Object Refinery Limited);
- * Contributor(s): -;
- *
- * $Id: SerialDateUtilities.java,v 1.6 2005/11/16 15:58:40 taqua Exp $
- *
- * Changes (from 26-Oct-2001)
- * --------------------------
- * 26-Oct-2001 : Changed package to com.jrefinery.date.*;
- * 08-Dec-2001 : Dropped isLeapYear() method (DG);
- * 04-Mar-2002 : Renamed SerialDates.java --> SerialDateUtilities.java (DG);
- * 25-Jun-2002 : Fixed a bug in the dayCountActual() method (DG);
- * 03-Oct-2002 : Fixed errors reported by Checkstyle (DG);
- *
- */
- package org.jfree.date;
- import java.text.DateFormatSymbols;
- import java.util.Calendar;
- /**
- * A utility class that provides a number of useful methods (some static).
- * Many of these are used in the implementation of the day-count convention
- * classes. I recognise some limitations in this implementation:
- * <p>
- * [1] some of the methods assume that the default Calendar is a
- * GregorianCalendar (used mostly to determine leap years) - so the code
- * won’t work if some other Calendar is the default. I'm not sure how
- * to handle this properly?
- * <p>
- * [2] a whole bunch of static methods isn't very object-oriented - but I couldn't think of a good
- * way to extend the Date and Calendar classes to add the functions I required,
- * so static methods are doing the job for now.
- *
- * @author David Gilbert
- */
- public class SerialDateUtilities {
- /** The default date format symbols. */
- private DateFormatSymbols dateFormatSymbols;
- /** Strings representing the weekdays. */
- private String[] weekdays;
- /** Strings representing the months. */
- private String[] months;
- /**
- * Creates a new utility class for the default locale.
- */
- public SerialDateUtilities() {
- this.dateFormatSymbols = new DateFormatSymbols();
- this.weekdays = this.dateFormatSymbols.getWeekdays();
- this.months = this.dateFormatSymbols.getMonths();
- }
- /**
- * Returns an array of strings representing the days-of-the-week.
- *
- * @return an array of strings representing the days-of-the-week.
- */
- public String[] getWeekdays() {
- return this.weekdays;
- }
- /**
- * Returns an array of strings representing the months.
- *
- * @return an array of strings representing the months.
- */
- public String[] getMonths() {
- return this.months;
- }
- /**
- * Converts the specified string to a weekday, using the default locale.
- *
- * @param s a string representing the day-of-the-week.
- *
- * @return an integer representing the day-of-the-week.
- */
- public int stringToWeekday(final String s) {
- if (s.equals(this.weekdays[Calendar.SATURDAY])) {
- return SerialDate.SATURDAY;
- }
- else if (s.equals(this.weekdays[Calendar.SUNDAY])) {
- return SerialDate.SUNDAY;
- }
- else if (s.equals(this.weekdays[Calendar.MONDAY])) {
- return SerialDate.MONDAY;
- }
- else if (s.equals(this.weekdays[Calendar.TUESDAY])) {
- return SerialDate.TUESDAY;
- }
- else if (s.equals(this.weekdays[Calendar.WEDNESDAY])) {
- return SerialDate.WEDNESDAY;
- }
- else if (s.equals(this.weekdays[Calendar.THURSDAY])) {
- return SerialDate.THURSDAY;
- }
- else {
- return SerialDate.FRIDAY;
- }
- }
- /**
- * Returns the actual number of days between two dates.
- *
- * @param start the start date.
- * @param end the end date.
- *
- * @return the number of days between the start date and the end date.
- */
- public static int dayCountActual(final SerialDate start, final SerialDate end) {
- return end.compare(start);
- }
- /**
- * Returns the number of days between the specified start and end dates,
- * assuming that there are thirty days in every month (that is,
- * corresponding to the 30/360 day-count convention).
- * <P>
- * The method handles cases where the start date is before the end date (by
- * switching the dates and returning a negative result).
- *
- * @param start the start date.
- * @param end the end date.
- *
- * @return the number of days between the two dates, assuming the 30/360 day-count convention.
- */
- public static int dayCount30(final SerialDate start, final SerialDate end) {
- final int d1;
- final int m1;
- final int y1;
- final int d2;
- final int m2;
- final int y2;
- if (start.isBefore(end)) { // check the order of the dates
- d1 = start.getDayOfMonth();
- m1 = start.getMonth();
- y1 = start.getYYYY();
- d2 = end.getDayOfMonth();
- m2 = end.getMonth();
- y2 = end.getYYYY();
- return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
- }
- else {
- return -dayCount30(end, start);
- }
- }
- /**
- * Returns the number of days between the specified start and end dates,
- * assuming that there are thirty days in every month, and applying the
- * ISDA adjustments (that is, corresponding to the 30/360 (ISDA) day-count
- * convention).
- * <P>
- * The method handles cases where the start date is before the end date (by
- * switching the dates around and returning a negative result).
- *
- * @param start the start date.
- * @param end the end date.
- *
- * @return The number of days between the two dates, assuming the 30/360
- * (ISDA) day-count convention.
- */
- public static int dayCount30ISDA(final SerialDate start, final SerialDate end) {
- int d1;
- final int m1;
- final int y1;
- int d2;
- final int m2;
- final int y2;
- if (start.isBefore(end)) {
- d1 = start.getDayOfMonth();
- m1 = start.getMonth();
- y1 = start.getYYYY();
- if (d1 == 31) { // first ISDA adjustment
- d1 = 30;
- }
- d2 = end.getDayOfMonth();
- m2 = end.getMonth();
- y2 = end.getYYYY();
- if ((d2 == 31) && (d1 == 30)) { // second ISDA adjustment
- d2 = 30;
- }
- return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
- }
- else if (start.isAfter(end)) {
- return -dayCount30ISDA(end, start);
- }
- else {
- return 0;
- }
- }
- /**
- * Returns the number of days between the specified start and end dates,
- * assuming that there are thirty days in every month, and applying the PSA
- * adjustments (that is, corresponding to the 30/360 (PSA) day-count convention).
- * The method handles cases where the start date is before the end date (by
- * switching the dates around and returning a negative result).
- *
- * @param start the start date.
- * @param end the end date.
- *
- * @return The number of days between the two dates, assuming the 30/360
- * (PSA) day-count convention.
- */
- public static int dayCount30PSA(final SerialDate start, final SerialDate end) {
- int d1;
- final int m1;
- final int y1;
- int d2;
- final int m2;
- final int y2;
- if (start.isOnOrBefore(end)) { // check the order of the dates
- d1 = start.getDayOfMonth();
- m1 = start.getMonth();
- y1 = start.getYYYY();
- if (SerialDateUtilities.isLastDayOfFebruary(start)) {
- d1 = 30;
- }
- if ((d1 == 31) || SerialDateUtilities.isLastDayOfFebruary(start)) {
- // first PSA adjustment
- d1 = 30;
- }
- d2 = end.getDayOfMonth();
- m2 = end.getMonth();
- y2 = end.getYYYY();
- if ((d2 == 31) && (d1 == 30)) { // second PSA adjustment
- d2 = 30;
- }
- return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
- }
- else {
- return -dayCount30PSA(end, start);
- }
- }
- /**
- * Returns the number of days between the specified start and end dates,
- * assuming that there are thirty days in every month, and applying the
- * European adjustment (that is, corresponding to the 30E/360 day-count
- * convention).
- * <P>
- * The method handles cases where the start date is before the end date (by
- * switching the dates around and returning a negative result).
- *
- * @param start the start date.
- * @param end the end date.
- *
- * @return the number of days between the two dates, assuming the 30E/360
- * day-count convention.
- */
- public static int dayCount30E(final SerialDate start, final SerialDate end) {
- int d1;
- final int m1;
- final int y1;
- int d2;
- final int m2;
- final int y2;
- if (start.isBefore(end)) {
- d1 = start.getDayOfMonth();
- m1 = start.getMonth();
- y1 = start.getYYYY();
- if (d1 == 31) { // first European adjustment
- d1 = 30;
- }
- d2 = end.getDayOfMonth();
- m2 = end.getMonth();
- y2 = end.getYYYY();
- if (d2 == 31) { // first European adjustment
- d2 = 30;
- }
- return 360 * (y2 - y1) + 30 * (m2 - m1) + (d2 - d1);
- }
- else if (start.isAfter(end)) {
- return -dayCount30E(end, start);
- }
- else {
- return 0;
- }
- }
- /**
- * Returns true if the specified date is the last day in February (that is, the
- * 28th in non-leap years, and the 29th in leap years).
- *
- * @param d the date to be tested.
- *
- * @return a boolean that indicates whether or not the specified date is
- * the last day of February.
- */
- public static boolean isLastDayOfFebruary(final SerialDate d) {
- final int dom;
- if (d.getMonth() == MonthConstants.FEBRUARY) {
- dom = d.getDayOfMonth();
- if (SerialDate.isLeapYear(d.getYYYY())) {
- return (dom == 29);
- }
- else {
- return (dom == 28);
- }
- }
- else { // not even February
- return false;
- }
- }
- /**
- * Returns the number of times that February 29 falls within the specified
- * date range. The result needs to correspond to the ACT/365 (Japanese)
- * day-count convention. The difficult cases are where the start or the
- * end date is Feb 29 (include or not?). Need to find out how JGBs do this
- * (since this is where the ACT/365 (Japanese) convention comes from ...
- *
- * @param start the start date.
- * @param end the end date.
- *
- * @return the number of times that February 29 occurs within the date
- * range.
- */
- public static int countFeb29s(final SerialDate start, final SerialDate end) {
- int count = 0;
- SerialDate feb29;
- final int y1;
- final int y2;
- int year;
- // check the order of the dates
- if (start.isBefore(end)) {
- y1 = start.getYYYY();
- y2 = end.getYYYY();
- for (year = y1; year == y2; year++) {
- if (SerialDate.isLeapYear(year)) {
- feb29 = SerialDate.createInstance(29, MonthConstants.FEBRUARY, year);
- if (feb29.isInRange(start, end, SerialDate.INCLUDE_SECOND)) {
- count++;
- }
- }
- }
- return count;
- }
- else {
- return countFeb29s(end, start);
- }
- }
- }