001    /*
002     Copyright (C) 2007 Richard Gomes
003    
004     This source code is release under the BSD License.
005    
006     This file is part of JQuantLib, a free-software/open-source library
007     for financial quantitative analysts and developers - http://jquantlib.org/
008    
009     JQuantLib is free software: you can redistribute it and/or modify it
010     under the terms of the JQuantLib license.  You should have received a
011     copy of the license along with this program; if not, please email
012     <jquant-devel@lists.sourceforge.net>. The license is also available online at
013     <http://www.jquantlib.org/index.php/LICENSE.TXT>.
014    
015     This program is distributed in the hope that it will be useful, but WITHOUT
016     ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
017     FOR A PARTICULAR PURPOSE.  See the license for more details.
018    
019     JQuantLib is based on QuantLib. http://quantlib.org/
020     When applicable, the original copyright notice follows this notice.
021     */
022    
023    package org.jquantlib.daycounters;
024    
025    import org.jquantlib.lang.annotation.QualityAssurance;
026    import org.jquantlib.lang.annotation.QualityAssurance.Quality;
027    import org.jquantlib.lang.annotation.QualityAssurance.Version;
028    import org.jquantlib.time.Date;
029    
030    /**
031     * Simple day counter for reproducing theoretical calculations.
032     * <p>
033     * This day counter tries to ensure that whole-month distances are returned as a
034     * simple fraction, i.e., 1 year = 1.0, 6 months = 0.5, 3 months = 0.25 and so
035     * forth.
036     *
037     * @note This day counter should be used together with NullCalendar, which
038     *       ensures that dates at whole-month distances share the same day of
039     *       month. It is <b>not</b> guaranteed to work with any other calendar.
040     *
041     * @author Srinivas Hasti
042     * @author Richard Gomes
043     */
044    @QualityAssurance(quality=Quality.Q4_UNIT, version=Version.V097, reviewers="Richard Gomes")
045    public class SimpleDayCounter extends DayCounter {
046    
047    
048        public SimpleDayCounter() {
049            super.impl = new Impl();
050        }
051    
052    
053        //
054        // private inner classes
055        //
056    
057        final private class Impl extends DayCounter.Impl {
058    
059            private final DayCounter fallback = new Thirty360();
060    
061            //
062            // implements DayCounter
063            //
064    
065            @Override
066            protected final String name() /* @ReadOnly */{
067                return "Simple";
068            }
069    
070            @Override
071            protected long dayCount(final Date dateStart, final Date dateEnd) /* @ReadOnly */ {
072                return fallback.dayCount(dateStart, dateEnd);
073            }
074    
075            @Override
076            protected /*@Time*/ final double yearFraction(
077                    final Date dateStart, final Date dateEnd,
078                    final Date refPeriodStart, final Date refPeriodEnd) /* @ReadOnly */{
079                final int dm1 = dateStart.dayOfMonth();
080                final int dm2 = dateEnd.dayOfMonth();
081                final int mm1 = dateStart.month().value();
082                final int mm2 = dateEnd.month().value();
083                final int yy1 = dateStart.year();
084                final int yy2 = dateEnd.year();
085    
086                if (dm1 == dm2 ||
087                        // e.g., Aug 30 -> Feb 28 ?
088                        (dm1 > dm2 && Date.isEndOfMonth(dateEnd)) ||
089                        // e.g., Feb 28 -> Aug 30 ?
090                        (dm1 < dm2 && Date.isEndOfMonth(dateStart)))
091                    return (yy2 - yy1) + (mm2 - mm1) / 12.0;
092                else
093                    return fallback.yearFraction(dateStart, dateEnd, refPeriodStart, refPeriodEnd);
094            }
095    
096        }
097    
098    }