serialdateutilities.java

来自「JfreeChart 常用图表例子」· Java 代码 · 共 384 行

JAVA
384
字号
/* =================================================== * JCommon : a free general purpose Java class library * =================================================== * * Project Info:  http://www.jfree.org/jcommon/index.html * Project Lead:  David Gilbert (david.gilbert@object-refinery.com); * * (C) Copyright 2000-2003, by Object Refinery Limited and Contributors. * * 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., 59 Temple Place, Suite 330, * Boston, MA 02111-1307, USA. * * ------------------------ * 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.4 2005/06/01 14:12:28 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&rsquo;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);        }    }}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?