DateUtil.java

  1. package org.drip.analytics.date;

  2. /*
  3.  * -*- mode: java; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  4.  */

  5. /*!
  6.  * Copyright (C) 2020 Lakshmi Krishnamurthy
  7.  * Copyright (C) 2019 Lakshmi Krishnamurthy
  8.  * Copyright (C) 2018 Lakshmi Krishnamurthy
  9.  * Copyright (C) 2017 Lakshmi Krishnamurthy
  10.  * Copyright (C) 2016 Lakshmi Krishnamurthy
  11.  * Copyright (C) 2015 Lakshmi Krishnamurthy
  12.  * Copyright (C) 2014 Lakshmi Krishnamurthy
  13.  *
  14.  *  This file is part of DROP, an open-source library targeting analytics/risk, transaction cost analytics,
  15.  *      asset liability management analytics, capital, exposure, and margin analytics, valuation adjustment
  16.  *      analytics, and portfolio construction analytics within and across fixed income, credit, commodity,
  17.  *      equity, FX, and structured products. It also includes auxiliary libraries for algorithm support,
  18.  *      numerical analysis, numerical optimization, spline builder, model validation, statistical learning,
  19.  *      and computational support.
  20.  *  
  21.  *      https://lakshmidrip.github.io/DROP/
  22.  *  
  23.  *  DROP is composed of three modules:
  24.  *  
  25.  *  - DROP Product Core - https://lakshmidrip.github.io/DROP-Product-Core/
  26.  *  - DROP Portfolio Core - https://lakshmidrip.github.io/DROP-Portfolio-Core/
  27.  *  - DROP Computational Core - https://lakshmidrip.github.io/DROP-Computational-Core/
  28.  *
  29.  *  DROP Product Core implements libraries for the following:
  30.  *  - Fixed Income Analytics
  31.  *  - Loan Analytics
  32.  *  - Transaction Cost Analytics
  33.  *
  34.  *  DROP Portfolio Core implements libraries for the following:
  35.  *  - Asset Allocation Analytics
  36.  *  - Asset Liability Management Analytics
  37.  *  - Capital Estimation Analytics
  38.  *  - Exposure Analytics
  39.  *  - Margin Analytics
  40.  *  - XVA Analytics
  41.  *
  42.  *  DROP Computational Core implements libraries for the following:
  43.  *  - Algorithm Support
  44.  *  - Computation Support
  45.  *  - Function Analysis
  46.  *  - Model Validation
  47.  *  - Numerical Analysis
  48.  *  - Numerical Optimizer
  49.  *  - Spline Builder
  50.  *  - Statistical Learning
  51.  *
  52.  *  Documentation for DROP is Spread Over:
  53.  *
  54.  *  - Main                     => https://lakshmidrip.github.io/DROP/
  55.  *  - Wiki                     => https://github.com/lakshmiDRIP/DROP/wiki
  56.  *  - GitHub                   => https://github.com/lakshmiDRIP/DROP
  57.  *  - Repo Layout Taxonomy     => https://github.com/lakshmiDRIP/DROP/blob/master/Taxonomy.md
  58.  *  - Javadoc                  => https://lakshmidrip.github.io/DROP/Javadoc/index.html
  59.  *  - Technical Specifications => https://github.com/lakshmiDRIP/DROP/tree/master/Docs/Internal
  60.  *  - Release Versions         => https://lakshmidrip.github.io/DROP/version.html
  61.  *  - Community Credits        => https://lakshmidrip.github.io/DROP/credits.html
  62.  *  - Issues Catalog           => https://github.com/lakshmiDRIP/DROP/issues
  63.  *  - JUnit                    => https://lakshmidrip.github.io/DROP/junit/index.html
  64.  *  - Jacoco                   => https://lakshmidrip.github.io/DROP/jacoco/index.html
  65.  *
  66.  *  Licensed under the Apache License, Version 2.0 (the "License");
  67.  *      you may not use this file except in compliance with the License.
  68.  *  
  69.  *  You may obtain a copy of the License at
  70.  *      http://www.apache.org/licenses/LICENSE-2.0
  71.  *  
  72.  *  Unless required by applicable law or agreed to in writing, software
  73.  *      distributed under the License is distributed on an "AS IS" BASIS,
  74.  *      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  75.  *  
  76.  *  See the License for the specific language governing permissions and
  77.  *      limitations under the License.
  78.  */

  79. /**
  80.  * <i>DateUtil</i> contains Various Utilities for manipulating Date. The Julian Date - Gregorian Date Inter
  81.  * Conversion follows the following References:
  82.  *
  83.  *  <br><br>
  84.  *  <ul>
  85.  *      <li>
  86.  *          Fliegel, H. F., and T. C. van Flandern (1968): A Machine Algorithm for Processing Calendar Dates
  87.  *              <i>Communications of the ACM</i> <b>11</b> 657
  88.  *      </li>
  89.  *      <li>
  90.  *          Fenton, D. (2001): Julian to Calendar Date Conversion
  91.  *              http://mathforum.org/library/drmath/view/51907.html
  92.  *      </li>
  93.  *  </ul>
  94.  *
  95.  *  <br><br>
  96.  *  <ul>
  97.  *      <li><b>Module </b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/ProductCore.md">Product Core Module</a></li>
  98.  *      <li><b>Library</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/FixedIncomeAnalyticsLibrary.md">Fixed Income Analytics</a></li>
  99.  *      <li><b>Project</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/analytics/README.md">Date, Cash Flow, and Cash Flow Period Measure Generation Utilities</a></li>
  100.  *      <li><b>Package</b> = <a href = "https://github.com/lakshmiDRIP/DROP/tree/master/src/main/java/org/drip/analytics/date/README.md">Date and Time Creation, Manipulation, and Usage</a></li>
  101.  *  </ul>
  102.  *
  103.  * @author Lakshmi Krishnamurthy
  104.  */

  105. public class DateUtil {

  106.     /**
  107.      * HALF_SECOND Constant for Julian Date Construction
  108.      */

  109.     public static double HALFSECOND = 0.5;

  110.     /**
  111.      * JGREG Constant for Julian Date Construction
  112.      */

  113.     public static int JGREG = 15 + 31 * (10 + 12 * 1582);

  114.     /**
  115.      * LEFT_INCLUDE includes the start date in the Feb29 check
  116.      */

  117.     public static final int LEFT_INCLUDE = 1;

  118.     /**
  119.      * RIGHT_INCLUDE includes the end date in the Feb29 check
  120.      */

  121.     public static final int RIGHT_INCLUDE = 2;

  122.     /**
  123.      * Days of the week - Monday
  124.      */

  125.     public static final int MONDAY = 0;

  126.     /**
  127.      * Days of the week - Tuesday
  128.      */

  129.     public static final int TUESDAY = 1;

  130.     /**
  131.      * Days of the week - Wednesday
  132.      */

  133.     public static final int WEDNESDAY = 2;

  134.     /**
  135.      * Days of the week - Thursday
  136.      */

  137.     public static final int THURSDAY = 3;

  138.     /**
  139.      * Days of the week - Friday
  140.      */

  141.     public static final int FRIDAY = 4;

  142.     /**
  143.      * Days of the week - Saturday
  144.      */

  145.     public static final int SATURDAY = 5;

  146.     /**
  147.      * Days of the week - Sunday
  148.      */

  149.     public static final int SUNDAY = 6;

  150.     /**
  151.      * Integer Month - January
  152.      */

  153.     public static final int JANUARY = 1;

  154.     /**
  155.      * Integer Month - February
  156.      */

  157.     public static final int FEBRUARY = 2;

  158.     /**
  159.      * Integer Month - March
  160.      */

  161.     public static final int MARCH = 3;

  162.     /**
  163.      * Integer Month - April
  164.      */

  165.     public static final int APRIL = 4;

  166.     /**
  167.      * Integer Month - May
  168.      */

  169.     public static final int MAY = 5;

  170.     /**
  171.      * Integer Month - June
  172.      */

  173.     public static final int JUNE = 6;

  174.     /**
  175.      * Integer Month - July
  176.      */

  177.     public static final int JULY = 7;

  178.     /**
  179.      * Integer Month - August
  180.      */

  181.     public static final int AUGUST = 8;

  182.     /**
  183.      * Integer Month - September
  184.      */

  185.     public static final int SEPTEMBER = 9;

  186.     /**
  187.      * Integer Month - October
  188.      */

  189.     public static final int OCTOBER = 10;

  190.     /**
  191.      * Integer Month - November
  192.      */

  193.     public static final int NOVEMBER = 11;

  194.     /**
  195.      * Integer Month - December
  196.      */

  197.     public static final int DECEMBER = 12;

  198.     /**
  199.      * Convert YMD to an Integer Julian Date.
  200.      *
  201.      * @param iYear Year
  202.      * @param iMonth Month
  203.      * @param iDay Day
  204.      *
  205.      * @return Integer representing the Julian Date
  206.      *
  207.      * @throws java.lang.Exception Thrown if the Inputs are invalid
  208.      */

  209.     public static int ToJulian (
  210.         final int iYear,
  211.         final int iMonth,
  212.         final int iDay)
  213.         throws java.lang.Exception
  214.     {
  215.         if (0 > iYear || 0 > iMonth || 0 > iDay)
  216.             throw new java.lang.Exception ("DateUtil::ToJulian => Invalid Inputs");

  217.         int iM1 = (iMonth - 14) / 12;
  218.         int iY1 = iYear + 4800;
  219.         return 1461 * (iY1 + iM1) / 4 + 367 * (iMonth - 2 - 12 * iM1) / 12 -
  220.             (3 * ((iY1 + iM1 + 100) / 100)) / 4 + iDay - 32075;
  221.     }

  222.     /**
  223.      * Create an YYYY/MM/DD String from the Input Julian Integer
  224.      *
  225.      * @param iJulian Integer representing Julian Date
  226.      *
  227.      * @return YYYY/MM/DD Date String
  228.      */

  229.     public static java.lang.String YYYYMMDD (
  230.         final int iJulian)
  231.     {
  232.         int iP = iJulian + 68569;
  233.         int iQ = 4 * iP / 146097;
  234.         int iR = iP - (146097 * iQ + 3) / 4;
  235.         int iS = 4000 * (iR + 1) / 1461001;
  236.         int iT = iR - (1461 * iS / 4) + 31;
  237.         int iU = 80 * iT / 2447;
  238.         int iV = iU / 11;
  239.         int iY = 100 * (iQ - 49) + iS + iV;
  240.         int iM = iU + 2 - 12 * iV;
  241.         int iD = iT - (2447 * iU / 80);

  242.         return "" + iY + "/" + org.drip.numerical.common.FormatUtil.FormatDouble (iM, 2, 0, 1., false) + "/" +
  243.             org.drip.numerical.common.FormatUtil.FormatDouble (iD, 2, 0, 1., false);
  244.     }

  245.     /**
  246.      * Create an DD/MMM/YYYY String from the Input Julian Integer
  247.      *
  248.      * @param iJulian Integer representing Julian Date
  249.      *
  250.      * @return DD/MMM/YYYY Date String
  251.      */

  252.     public static java.lang.String DDMMMYYYY (
  253.         final int iJulian)
  254.     {
  255.         int iP = iJulian + 68569;
  256.         int iQ = 4 * iP / 146097;
  257.         int iR = iP - (146097 * iQ + 3) / 4;
  258.         int iS = 4000 * (iR + 1) / 1461001;
  259.         int iT = iR - (1461 * iS / 4) + 31;
  260.         int iU = 80 * iT / 2447;
  261.         int iV = iU / 11;
  262.         int iY = 100 * (iQ - 49) + iS + iV;
  263.         int iM = iU + 2 - 12 * iV;
  264.         int iD = iT - (2447 * iU / 80);

  265.         return org.drip.numerical.common.FormatUtil.FormatDouble (iD, 2, 0, 1., false) + "-" + MonthTrigram (iM)
  266.             + "-" + iY;
  267.     }

  268.     /**
  269.      * Return the Year corresponding to the Julian Date
  270.      *
  271.      * @param iJulian Integer representing Julian Date
  272.      *
  273.      * @return integer representing the month
  274.      *
  275.      * @throws java.lang.Exception Thrown if the Input Date in invalid
  276.      */

  277.     public static int Year (
  278.         final int iJulian)
  279.         throws java.lang.Exception
  280.     {
  281.         int iP = iJulian + 68569;
  282.         int iQ = 4 * iP / 146097;
  283.         int iR = iP - (146097 * iQ + 3) / 4;
  284.         int iS = 4000 * (iR + 1) / 1461001;
  285.         int iT = iR - (1461 * iS / 4) + 31;
  286.         int iU = 80 * iT / 2447;
  287.         int iV = iU / 11;
  288.         return 100 * (iQ - 49) + iS + iV;
  289.     }

  290.     /**
  291.      * Return the Month given the Julian Date represented by the Integer.
  292.      *
  293.      * @param iJulian Integer representing Julian Date
  294.      *
  295.      * @return Integer representing the Month
  296.      *
  297.      * @throws java.lang.Exception Thrown if the Input Date is invalid
  298.      */

  299.     public static int Month (
  300.         final int iJulian)
  301.         throws java.lang.Exception
  302.     {
  303.         int iP = iJulian + 68569;
  304.         int iQ = 4 * iP / 146097;
  305.         int iR = iP - (146097 * iQ + 3) / 4;
  306.         int iS = 4000 * (iR + 1) / 1461001;
  307.         int iT = iR - (1461 * iS / 4) + 31;
  308.         int iU = 80 * iT / 2447;
  309.         int iV = iU / 11;
  310.         return iU + 2 - 12 * iV;
  311.     }

  312.     /**
  313.      * Return the Date given the Julian Date represented by the Integer.
  314.      *
  315.      * @param iJulian Integer representing Julian Date
  316.      *
  317.      * @return Integer representing the Date
  318.      *
  319.      * @throws java.lang.Exception Thrown if the Input Date is invalid
  320.      */

  321.     public static int Date (
  322.         final int iJulian)
  323.         throws java.lang.Exception
  324.     {
  325.         int iP = iJulian + 68569;
  326.         int iQ = 4 * iP / 146097;
  327.         int iR = iP - (146097 * iQ + 3) / 4;
  328.         int iS = 4000 * (iR + 1) / 1461001;
  329.         int iT = iR - (1461 * iS / 4) + 31;
  330.         int iU = 80 * iT / 2447;
  331.         return iT - (2447 * iU / 80);
  332.     }

  333.     /**
  334.      * Return the Vintage corresponding to the Julian Date
  335.      *
  336.      * @param iJulian Integer representing Julian Date
  337.      *
  338.      * @return String Representing the Vintage
  339.      */

  340.     public static java.lang.String Vintage (
  341.         final int iJulian)
  342.     {
  343.         int iP = iJulian + 68569;
  344.         int iQ = 4 * iP / 146097;
  345.         int iR = iP - (146097 * iQ + 3) / 4;
  346.         int iS = 4000 * (iR + 1) / 1461001;
  347.         int iT = iR - (1461 * iS / 4) + 31;
  348.         int iU = 80 * iT / 2447;
  349.         int iV = iU / 11;
  350.         int iY = 100 * (iQ - 49) + iS + iV;
  351.         int iM = iU + 2 - 12 * iV;

  352.         return MonthTrigram (iM) + "-" + iY;
  353.     }

  354.     /**
  355.      * Number of Days elapsed in the Year represented by the given Julian Date
  356.      *
  357.      * @param iDate Integer representing Julian Date
  358.      *
  359.      * @return Integer representing the Number of Days in the Current Year
  360.      *
  361.      * @throws java.lang.Exception Thrown if the Input Date is invalid
  362.      */

  363.     public static final int DaysElapsed (
  364.         final int iDate)
  365.         throws java.lang.Exception
  366.     {
  367.         return iDate - ToJulian (Year (iDate), JANUARY, 1);
  368.     }

  369.     /**
  370.      * Number of Days remaining in the Year represented by the given Julian Date
  371.      *
  372.      * @param iDate Integer representing Julian Date
  373.      *
  374.      * @return Integer representing the Number of Days remaining in the Current Year
  375.      *
  376.      * @throws java.lang.Exception Thrown if the Input Date is invalid
  377.      */

  378.     public static final int DaysRemaining (
  379.         final int iDate)
  380.         throws java.lang.Exception
  381.     {
  382.         return ToJulian (Year (iDate), DECEMBER, 31) - iDate;
  383.     }

  384.     /**
  385.      * Indicate if the Year of the given Julian Date is a Leap Year
  386.      *
  387.      * @param iDate Input Date
  388.      *
  389.      * @return TRUE - Date falls on a Leap Year
  390.      *
  391.      * @throws java.lang.Exception Thrown if Input is invalid
  392.      */

  393.     public static final boolean IsLeapYear (
  394.         final int iDate)
  395.         throws java.lang.Exception
  396.     {
  397.         return 0 == (Year (iDate) % 4);
  398.     }

  399.     /**
  400.      * Indicate whether there is at least One Leap Day between 2 given Dates
  401.      *
  402.      * @param iStartDate The Start Date
  403.      * @param iEndDate The End Date
  404.      * @param iIncludeSide INCLUDE_LEFT or INCLUDE_RIGHT indicating whether the starting date, the ending
  405.      *  date, or both dates are to be included
  406.      *  
  407.      * @return TRUE - There is at least One Feb29 between the Dates
  408.      *
  409.      * @throws java.lang.Exception If inputs are invalid
  410.      */

  411.     public static final boolean ContainsFeb29 (
  412.         final int iStartDate,
  413.         final int iEndDate,
  414.         final int iIncludeSide)
  415.         throws java.lang.Exception
  416.     {
  417.         if (iStartDate >= iEndDate) return false;

  418.         int iLeftDate = iStartDate;
  419.         int iRightDate = iEndDate;

  420.         if (0 == (iIncludeSide & LEFT_INCLUDE)) ++iLeftDate;

  421.         if (0 == (iIncludeSide & RIGHT_INCLUDE)) --iRightDate;

  422.         for (int iDate = iLeftDate; iDate <= iRightDate; ++iDate) {
  423.             if (FEBRUARY == Month (iDate) && 29 == Date (iDate)) return true;
  424.         }

  425.         return false;
  426.     }

  427.     /**
  428.      * Calculate how many Leap Days exist between the 2 given Dates
  429.      *
  430.      * @param iStartDate The Start Date
  431.      * @param iEndDate The End Date
  432.      * @param iIncludeSide INCLUDE_LEFT or INCLUDE_RIGHT indicating whether the starting date, the ending
  433.      *  date, or both dates are to be included
  434.      *
  435.      * @return Number of Leap Days
  436.      *
  437.      * @throws java.lang.Exception Thrown if the Inputs are invalid
  438.      */

  439.     public static final int NumFeb29 (
  440.         final int iStartDate,
  441.         final int iEndDate,
  442.         final int iIncludeSide)
  443.         throws java.lang.Exception
  444.     {
  445.         int iNumFeb29 = 0;
  446.         boolean bLoop = true;
  447.         int iDate = iStartDate;

  448.         while (bLoop) {
  449.             int iPeriodEndDate = iDate + 365;

  450.             if (iPeriodEndDate > iEndDate) {
  451.                 bLoop = false;
  452.                 iPeriodEndDate = iEndDate;
  453.             }

  454.             if (ContainsFeb29 (iDate, iPeriodEndDate, iIncludeSide)) ++iNumFeb29;

  455.             iDate = iPeriodEndDate;
  456.         }

  457.         return iNumFeb29;
  458.     }

  459.     /**
  460.      * Return the English word corresponding to the input integer month
  461.      *  
  462.      * @param iMonth Integer representing the month
  463.      *
  464.      * @return String of the English word
  465.      */

  466.     public static final java.lang.String MonthChar (
  467.         final int iMonth)
  468.     {
  469.         if (JANUARY == iMonth) return "January";

  470.         if (FEBRUARY == iMonth) return "February";

  471.         if (MARCH == iMonth) return "March";

  472.         if (APRIL == iMonth) return "April";

  473.         if (MAY == iMonth) return "May";

  474.         if (JUNE == iMonth) return "June";

  475.         if (JULY == iMonth) return "July";

  476.         if (AUGUST == iMonth) return "August";

  477.         if (SEPTEMBER == iMonth) return "September";

  478.         if (OCTOBER == iMonth) return "October";

  479.         if (NOVEMBER == iMonth) return "November";

  480.         if (DECEMBER == iMonth) return "December";

  481.         return null;
  482.     }

  483.     /**
  484.      * Return the Month Trigram corresponding to the Input Integer Month
  485.      *
  486.      * @param iMonth Integer representing the Month
  487.      *
  488.      * @return String representing the Month Trigram (used, e.g., in Oracle DB)
  489.      */

  490.     public static java.lang.String MonthTrigram (
  491.         final int iMonth)
  492.     {
  493.         if (JANUARY == iMonth) return "JAN";

  494.         if (FEBRUARY == iMonth) return "FEB";

  495.         if (MARCH == iMonth) return "MAR";

  496.         if (APRIL == iMonth) return "APR";

  497.         if (MAY == iMonth) return "MAY";

  498.         if (JUNE == iMonth) return "JUN";

  499.         if (JULY == iMonth) return "JUL";

  500.         if (AUGUST == iMonth) return "AUG";

  501.         if (SEPTEMBER == iMonth) return "SEP";

  502.         if (OCTOBER == iMonth) return "OCT";

  503.         if (NOVEMBER == iMonth) return "NOV";

  504.         if (DECEMBER == iMonth) return "DEC";

  505.         return null;
  506.     }

  507.     /**
  508.      * Convert the month trigram/word to the corresponding month integer
  509.      *
  510.      * @param strMonth Month trigram or English Word
  511.      *
  512.      * @return Integer representing the Month
  513.      *
  514.      * @throws java.lang.Exception Thrown on Invalid Input Month
  515.      */

  516.     public static final int MonthFromMonthChars (
  517.         final java.lang.String strMonth)
  518.         throws java.lang.Exception
  519.     {
  520.         if (null == strMonth || strMonth.isEmpty())
  521.             throw new java.lang.Exception ("DateUtil::MonthFromMonthChars => Invalid Month!");

  522.         if (strMonth.equalsIgnoreCase ("JAN") || strMonth.equalsIgnoreCase ("JANUARY")) return JANUARY;

  523.         if (strMonth.equalsIgnoreCase ("FEB") || strMonth.equalsIgnoreCase ("FEBRUARY")) return FEBRUARY;

  524.         if (strMonth.equalsIgnoreCase ("MAR") || strMonth.equalsIgnoreCase ("MARCH")) return MARCH;

  525.         if (strMonth.equalsIgnoreCase ("APR") || strMonth.equalsIgnoreCase ("APRIL")) return APRIL;

  526.         if (strMonth.equalsIgnoreCase ("MAY")) return MAY;

  527.         if (strMonth.equalsIgnoreCase ("JUN") || strMonth.equalsIgnoreCase ("JUNE")) return JUNE;

  528.         if (strMonth.equalsIgnoreCase ("JUL") || strMonth.equalsIgnoreCase ("JULY")) return JULY;

  529.         if (strMonth.equalsIgnoreCase ("AUG") || strMonth.equalsIgnoreCase ("AUGUST")) return AUGUST;

  530.         if (strMonth.equalsIgnoreCase ("SEP") || strMonth.equalsIgnoreCase ("SEPTEMBER") ||
  531.             strMonth.equalsIgnoreCase ("SEPT"))
  532.             return SEPTEMBER;

  533.         if (strMonth.equalsIgnoreCase ("OCT") || strMonth.equalsIgnoreCase ("OCTOBER")) return OCTOBER;

  534.         if (strMonth.equalsIgnoreCase ("NOV") || strMonth.equalsIgnoreCase ("NOVEMBER")) return NOVEMBER;

  535.         if (strMonth.equalsIgnoreCase ("DEC") || strMonth.equalsIgnoreCase ("DECEMBER")) return DECEMBER;

  536.         throw new java.lang.Exception ("DateUtil::MonthFromMonthChars => Invalid Month: " + strMonth);
  537.     }

  538.     /**
  539.      * Get the English word for day corresponding to the input integer
  540.      *
  541.      * @param iDay Integer representing the day
  542.      *
  543.      * @return String representing the English word for the day
  544.      */

  545.     public static java.lang.String DayChars (
  546.         final int iDay)
  547.     {
  548.         if (MONDAY == iDay) return "Monday";

  549.         if (TUESDAY == iDay) return "Tuesday";

  550.         if (WEDNESDAY == iDay) return "Wednesday";

  551.         if (THURSDAY == iDay) return "Thursday";

  552.         if (FRIDAY == iDay) return "Friday";

  553.         if (SATURDAY == iDay) return "Saturday";

  554.         if (SUNDAY == iDay) return "Sunday";

  555.         return "";
  556.     }

  557.     /**
  558.      * Get the maximum number of days in the given month and year
  559.      *
  560.      * @param iMonth Integer representing the month
  561.      * @param iYear Integer representing the year
  562.      *
  563.      * @return Integer representing the maximum days
  564.      *
  565.      * @throws java.lang.Exception Thrown if inputs are invalid
  566.      */

  567.     public static final int DaysInMonth (
  568.         final int iMonth,
  569.         final int iYear)
  570.         throws java.lang.Exception
  571.     {
  572.         if (JANUARY == iMonth) return 31;

  573.         if (FEBRUARY == iMonth) return 0 == (iYear % 4) ? 29 : 28;

  574.         if (MARCH == iMonth) return 31;

  575.         if (APRIL == iMonth) return 30;

  576.         if (MAY == iMonth) return 31;

  577.         if (JUNE == iMonth) return 30;

  578.         if (JULY == iMonth) return 31;

  579.         if (AUGUST == iMonth) return 31;

  580.         if (SEPTEMBER == iMonth) return 30;

  581.         if (OCTOBER == iMonth) return 31;

  582.         if (NOVEMBER == iMonth) return 30;

  583.         if (DECEMBER == iMonth) return 31;

  584.         throw new java.lang.Exception ("DateUtil::DaysInMonth => Invalid Month: " + iMonth);
  585.     }

  586.     /**
  587.      * Indicate if the given Date corresponds to a Month End
  588.      *
  589.      * @param iDate The Date
  590.      *
  591.      * @return TRUE - Date Corresponds to EOM
  592.      *
  593.      * @throws java.lang.Exception Thrown if input date is invalid
  594.      */

  595.     public static final boolean IsEOM (
  596.         final int iDate)
  597.         throws java.lang.Exception
  598.     {
  599.         return Date (iDate) == DaysInMonth (Month (iDate), Year (iDate)) ? true : false;
  600.     }

  601.     /**
  602.      * Create a JulianDate from the Year/Month/Date
  603.      *  
  604.      * @param iYear Year
  605.      * @param iMonth Month
  606.      * @param iDate Date
  607.      *
  608.      * @return Julian Date corresponding to the specified Year/Month/Date
  609.      */

  610.     public static final org.drip.analytics.date.JulianDate CreateFromYMD (
  611.         final int iYear,
  612.         final int iMonth,
  613.         final int iDate)
  614.     {
  615.         try {
  616.             return new org.drip.analytics.date.JulianDate (ToJulian (iYear, iMonth, iDate));
  617.         } catch (java.lang.Exception e) {
  618.             e.printStackTrace();
  619.         }

  620.         return null;
  621.     }

  622.     /**
  623.      * Return a Julian Date corresponding to Today
  624.      *  
  625.      * @return JulianDate corresponding to Today
  626.      */

  627.     public static final org.drip.analytics.date.JulianDate Today()
  628.     {
  629.         java.util.Date dtNow = new java.util.Date();

  630.         try {
  631.             return CreateFromYMD (Year (dtNow), Month (dtNow), Day (dtNow));
  632.         } catch (java.lang.Exception e) {
  633.             e.printStackTrace();
  634.         }

  635.         return null;
  636.     }

  637.     /**
  638.      * Create a JulianDate from a String containing the Date in the DDMMMYYYY Format
  639.      *
  640.      * @param strDate String containing the Date in the DDMMMYYYY Format
  641.      *
  642.      * @return The JulianDate Instance
  643.      */

  644.     public static final JulianDate CreateFromDDMMMYYYY (
  645.         final java.lang.String strDate)
  646.     {
  647.         if (null == strDate || strDate.isEmpty()) return null;

  648.         java.lang.String[] astrParts = strDate.split ("-");

  649.         if (3 != astrParts.length) return null;

  650.         try {
  651.             return CreateFromYMD (java.lang.Integer.parseInt (astrParts[2]), MonthFromMonthChars (astrParts[1]),
  652.                 java.lang.Integer.parseInt (astrParts[0]));
  653.         } catch (java.lang.Exception e) {
  654.         }

  655.         return null;
  656.     }

  657.     /**
  658.      * Create a JulianDate from a String containing Date in the DDMMYYYY Format
  659.      *
  660.      * @param strMDY String containing Date in the MM/DD/YYYY Format
  661.      * @param strDelim String Delimiter
  662.      *
  663.      * @return The JulianDate Instance
  664.      */

  665.     public static final org.drip.analytics.date.JulianDate CreateFromMDY (
  666.         final java.lang.String strMDY,
  667.         final java.lang.String strDelim)
  668.     {
  669.         if (null == strMDY || strMDY.isEmpty() || null == strDelim || strDelim.isEmpty()) return null;

  670.         java.lang.String[] astrParts = strMDY.split (strDelim);

  671.         if (3 != astrParts.length) return null;

  672.         try {
  673.             return CreateFromYMD (java.lang.Integer.parseInt (astrParts[2]), java.lang.Integer.parseInt (astrParts[0]),
  674.                 java.lang.Integer.parseInt (astrParts[1]));
  675.         } catch (java.lang.Exception e) {
  676.         }

  677.         return null;
  678.     }

  679.     /**
  680.      * Create a JulianDate from a String containing Date in the YYYYMMDD Format
  681.      *
  682.      * @param strYMD String containing Date in the YYYYMMDD Format
  683.      * @param strDelim String Delimiter
  684.      *
  685.      * @return The JulianDate Instance
  686.      */

  687.     public static final org.drip.analytics.date.JulianDate CreateFromYMD (
  688.         final java.lang.String strYMD,
  689.         final java.lang.String strDelim)
  690.     {
  691.         if (null == strYMD || strYMD.isEmpty() || null == strDelim || strDelim.isEmpty()) return null;

  692.         java.lang.String[] astrParts = strYMD.split (strDelim);

  693.         if (3 != astrParts.length) return null;

  694.         try {
  695.             return CreateFromYMD (java.lang.Integer.parseInt (astrParts[0]), java.lang.Integer.parseInt (astrParts[1]),
  696.                 java.lang.Integer.parseInt (astrParts[2]));
  697.         } catch (java.lang.Exception e) {
  698.         }

  699.         return null;
  700.     }

  701.     /**
  702.      * Return the Day of the Week corresponding to the java.util.Date Instance
  703.      *
  704.      * @param dt The java.util.Date Instance
  705.      *
  706.      * @return The Day Of The Week
  707.      *
  708.      * @throws java.lang.Exception Thrown if Input Date is invalid
  709.      */

  710.     public static final int DayOfTheWeek (
  711.         final java.util.Date dt)
  712.         throws java.lang.Exception
  713.     {
  714.         if (null == dt) throw new java.lang.Exception ("DateUtil::DayOfTheWeek => Invalid Date");

  715.         java.util.Calendar cal = java.util.Calendar.getInstance();

  716.         cal.setTime (dt);

  717.         return cal.get (java.util.Calendar.DAY_OF_WEEK);
  718.     }

  719.     /**
  720.      * Return the Day corresponding to the java.util.Date Instance
  721.      *
  722.      * @param dt The java.util.Date Instance
  723.      *
  724.      * @return The Day
  725.      *
  726.      * @throws java.lang.Exception Thrown if Inputs are Invalid
  727.      */

  728.     public static final int Day (
  729.         final java.util.Date dt)
  730.         throws java.lang.Exception
  731.     {
  732.         if (null == dt) throw new java.lang.Exception ("DateUtil::Day => Invalid Date");

  733.         java.util.Calendar cal = java.util.Calendar.getInstance();

  734.         cal.setTime (dt);

  735.         return cal.get (java.util.Calendar.DATE);
  736.     }

  737.     /**
  738.      * Return the Month corresponding to the java.util.Date Instance. 1 is January, and 12 is December
  739.      *
  740.      * @param dt The java.util.Date Instance
  741.      *
  742.      * @return The Month
  743.      *
  744.      * @throws java.lang.Exception Thrown if Inputs are Invalid
  745.      */

  746.     public static final int Month (
  747.         final java.util.Date dt)
  748.         throws java.lang.Exception
  749.     {
  750.         if (null == dt) throw new java.lang.Exception ("DateUtil::Month => Invalid Date");

  751.         java.util.Calendar cal = java.util.Calendar.getInstance();

  752.         cal.setTime (dt);

  753.         return cal.get (java.util.Calendar.MONTH) + 1;
  754.     }

  755.     /**
  756.      * Return the Year corresponding to the java.util.Date Instance
  757.      *
  758.      * @param dt The java.util.Date Instance
  759.      *
  760.      * @return The Year
  761.      *
  762.      * @throws java.lang.Exception Thrown if Inputs are Invalid
  763.      */

  764.     public static final int Year (
  765.         final java.util.Date dt)
  766.         throws java.lang.Exception
  767.     {
  768.         if (null == dt) throw new java.lang.Exception ("DateUtil::Year => Invalid Date");

  769.         java.util.Calendar cal = java.util.Calendar.getInstance();

  770.         cal.setTime (dt);

  771.         return cal.get (java.util.Calendar.YEAR);
  772.     }

  773.     /**
  774.      * Create an Oracle Date Trigram from a YYYYMMDD String
  775.      *
  776.      * @param strYYYYMMDD Date String in the YYYYMMDD Format.
  777.      *
  778.      * @return Oracle Date Trigram String
  779.      */

  780.     public static java.lang.String MakeOracleDateFromYYYYMMDD (
  781.         final java.lang.String strYYYYMMDD)
  782.     {
  783.         if (null == strYYYYMMDD || strYYYYMMDD.isEmpty()) return null;

  784.         try {
  785.             return strYYYYMMDD.substring (6) + "-" + MonthTrigram ((java.lang.Integer.parseInt
  786.                 (strYYYYMMDD.substring (4, 6)))) + "-" + strYYYYMMDD.substring (0, 4);
  787.         } catch (java.lang.Exception e) {
  788.             e.printStackTrace();
  789.         }

  790.         return null;
  791.     }

  792.     /**
  793.      * Create an Oracle date trigram from a Bloomberg date string
  794.      *
  795.      * @param strBBGDate Bloomberg date string
  796.      *
  797.      * @return Oracle date trigram string
  798.      */

  799.     public static java.lang.String MakeOracleDateFromBBGDate (
  800.         final java.lang.String strBBGDate)
  801.     {
  802.         if (null == strBBGDate || strBBGDate.isEmpty()) return null;

  803.         java.util.StringTokenizer st = new java.util.StringTokenizer (strBBGDate, "/");

  804.         try {
  805.             java.lang.String strMonth = MonthTrigram (java.lang.Integer.parseInt (st.nextToken()));

  806.             if (null == strMonth) return null;

  807.             return st.nextToken() + "-" + strMonth + "-" + st.nextToken();
  808.         } catch (java.lang.Exception e) {
  809.             e.printStackTrace();
  810.         }

  811.         return null;
  812.     }

  813.     /**
  814.      * Create a JulianDate from the java Date
  815.      *
  816.      * @param dt Java Date input
  817.      *
  818.      * @return JulianDate output
  819.      */

  820.     public static final org.drip.analytics.date.JulianDate MakeJulianFromRSEntry (
  821.         final java.util.Date dt)
  822.     {
  823.         if (null == dt) return null;

  824.         try {
  825.             return CreateFromYMD (Year (dt), Month (dt), Day (dt));
  826.         } catch (java.lang.Exception e) {
  827.             e.printStackTrace();
  828.         }

  829.         return null;
  830.     }

  831.     /**
  832.      * Retrieve a Java Date Instance from the Julian Date Instance
  833.      *
  834.      * @param dt Julian Date Instance
  835.      *
  836.      * @return The Java Date Instance
  837.      */

  838.     public static final java.util.Date JavaDateFromJulianDate (
  839.         final org.drip.analytics.date.JulianDate dt)
  840.     {
  841.         if (null == dt) return null;

  842.         java.util.Calendar cal = java.util.Calendar.getInstance();

  843.         int iDate = dt.julian();

  844.         try {
  845.             cal.set (Year (iDate), Month (iDate) - 1, Date (iDate));
  846.         } catch (java.lang.Exception e) {
  847.             e.printStackTrace();

  848.             return null;
  849.         }

  850.         return cal.getTime();
  851.     }

  852.     /**
  853.      * Create a JulianDate from the DD MMM YY
  854.      *
  855.      * @param strDDMMMYY Java Date input as delimited DD MMM YY
  856.      * @param strDelim Delimiter
  857.      *
  858.      * @return JulianDate output
  859.      */

  860.     public static final org.drip.analytics.date.JulianDate MakeJulianFromDDMMMYY (
  861.         final java.lang.String strDDMMMYY,
  862.         final java.lang.String strDelim)
  863.     {
  864.         if (null == strDDMMMYY || strDDMMMYY.isEmpty() || null == strDelim || strDelim.isEmpty())
  865.             return null;

  866.         java.lang.String[] astrDMY = strDDMMMYY.split (strDelim);

  867.         if (null == astrDMY || 3 != astrDMY.length) return null;

  868.         try {
  869.             return CreateFromYMD (2000 + java.lang.Integer.parseInt (astrDMY[2].trim()), MonthFromMonthChars
  870.                 (astrDMY[1].trim()), java.lang.Integer.parseInt (astrDMY[0].trim()));
  871.         } catch (java.lang.Exception e) {
  872.             e.printStackTrace();
  873.         }

  874.         return null;
  875.     }

  876.     /**
  877.      * Create a JulianDate from the YYYY MM DD
  878.      *
  879.      * @param strYYYYMMDD Java Date input as delimited YYYY MM DD
  880.      * @param strDelim Delimiter
  881.      *
  882.      * @return JulianDate output
  883.      */

  884.     public static final org.drip.analytics.date.JulianDate MakeJulianFromYYYYMMDD (
  885.         final java.lang.String strYYYYMMDD,
  886.         final java.lang.String strDelim)
  887.     {
  888.         if (null == strYYYYMMDD || strYYYYMMDD.isEmpty() || null == strDelim || strDelim.isEmpty())
  889.             return null;

  890.         java.lang.String[] astrYYYYMMDD = strYYYYMMDD.split (strDelim);

  891.         if (null == astrYYYYMMDD || 3 != astrYYYYMMDD.length) return null;

  892.         try {
  893.             return CreateFromYMD (java.lang.Integer.parseInt (astrYYYYMMDD[0].trim()), java.lang.Integer.parseInt
  894.                 (astrYYYYMMDD[1].trim()), java.lang.Integer.parseInt (astrYYYYMMDD[2].trim()));
  895.         } catch (java.lang.Exception e) {
  896.             e.printStackTrace();
  897.         }

  898.         return null;
  899.     }

  900.     /**
  901.      * Create a JulianDate from the MDY
  902.      *
  903.      * @param strMDY Java Date input as delimited M/D/Y
  904.      * @param strDelim Delimiter
  905.      *
  906.      * @return JulianDate output
  907.      */

  908.     public static final org.drip.analytics.date.JulianDate FromMDY (
  909.         final java.lang.String strMDY,
  910.         final java.lang.String strDelim)
  911.     {
  912.         if (null == strMDY || strMDY.isEmpty() || null == strDelim || strDelim.isEmpty())
  913.             return null;

  914.         java.lang.String[] astrDMY = strMDY.split (strDelim);

  915.         if (null == astrDMY || 3 != astrDMY.length) return null;

  916.         try {
  917.             return CreateFromYMD (java.lang.Integer.parseInt (astrDMY[2].trim()), java.lang.Integer.parseInt
  918.                 (astrDMY[0].trim()), java.lang.Integer.parseInt (astrDMY[1].trim()));
  919.         } catch (java.lang.Exception e) {
  920.             e.printStackTrace();
  921.         }

  922.         return null;
  923.     }

  924.     /**
  925.      * Create a JulianDate from Bloomberg date string
  926.      *
  927.      * @param strBBGDate Bloomberg date string
  928.      *
  929.      * @return The new JulianDate
  930.      */

  931.     public static final org.drip.analytics.date.JulianDate MakeJulianDateFromBBGDate (
  932.         final java.lang.String strBBGDate)
  933.     {
  934.         if (null == strBBGDate || strBBGDate.isEmpty()) return null;

  935.         java.lang.String[] astrFields = strBBGDate.split ("/");

  936.         if (3 != astrFields.length) return null;

  937.         try {
  938.             return CreateFromYMD (
  939.                 (int) java.lang.Double.parseDouble (astrFields[2].trim()),
  940.                 (int) java.lang.Double.parseDouble (astrFields[0].trim()),
  941.                 (int) java.lang.Double.parseDouble (astrFields[1].trim())
  942.             );
  943.         } catch (java.lang.Exception e) {
  944.             e.printStackTrace();
  945.         }

  946.         return null;
  947.     }

  948.     /**
  949.      * Retrieve the Month corresponding to the Month Digit Code
  950.      *
  951.      * @param ch The Month Digit Code
  952.      *
  953.      * @return The Month corresponding to the Month Digit Code
  954.      *
  955.      * @throws java.lang.Exception Thrown if the Digit Code is Invalid
  956.      */

  957.     public static final int MonthFromCode (
  958.         final char ch)
  959.         throws java.lang.Exception
  960.     {
  961.         if ('F' == ch) return JANUARY;

  962.         if ('G' == ch) return FEBRUARY;

  963.         if ('H' == ch) return MARCH;

  964.         if ('J' == ch) return APRIL;

  965.         if ('K' == ch) return MAY;

  966.         if ('M' == ch) return JUNE;

  967.         if ('N' == ch) return JULY;

  968.         if ('Q' == ch) return AUGUST;

  969.         if ('U' == ch) return SEPTEMBER;

  970.         if ('V' == ch) return OCTOBER;

  971.         if ('X' == ch) return NOVEMBER;

  972.         if ('Z' == ch) return DECEMBER;

  973.         throw new java.lang.Exception ("DateUtil::MonthFromCode => Invalid Character: " + ch);
  974.     }

  975.     /**
  976.      * Retrieve the Digit Code corresponding to the Month
  977.      *
  978.      * @param iMonth The Month
  979.      *
  980.      * @return The Digit Code corresponding to the Month
  981.      *
  982.      * @throws java.lang.Exception Thrown if the Digit Code cannot be computed
  983.      */

  984.     public static final char CodeFromMonth (
  985.         final int iMonth)
  986.         throws java.lang.Exception
  987.     {
  988.         if (JANUARY == iMonth) return 'F';

  989.         if (FEBRUARY == iMonth) return 'G';

  990.         if (MARCH == iMonth) return 'H';

  991.         if (APRIL == iMonth) return 'J';

  992.         if (MAY == iMonth) return 'K';

  993.         if (JUNE == iMonth) return 'M';

  994.         if (JULY == iMonth) return 'N';

  995.         if (AUGUST == iMonth) return 'Q';

  996.         if (SEPTEMBER == iMonth) return 'U';

  997.         if (OCTOBER == iMonth) return 'V';

  998.         if (NOVEMBER == iMonth) return 'X';

  999.         if (DECEMBER == iMonth) return 'Z';

  1000.         throw new java.lang.Exception ("DateUtil::CodeFromMonth => Invalid Month: " + iMonth);
  1001.     }
  1002. }