1712 lines
70 KiB
C#
1712 lines
70 KiB
C#
//============================================================================
|
|
//ZedGraph Class Library - A Flexible Line Graph/Bar Graph Library in C#
|
|
//Copyright ?2004 John Champion
|
|
//
|
|
//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
|
|
//=============================================================================
|
|
|
|
using System;
|
|
|
|
namespace DrawGraph
|
|
{
|
|
|
|
/// <summary>
|
|
/// This struct encapsulates a date and time value, and handles associated
|
|
/// calculations and conversions between various formats.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// This format stored as a double value representing days since a reference date
|
|
/// (XL date 0.0 is December 30, 1899 at 00:00 hrs).
|
|
/// Negative values are permissible, and the
|
|
/// range of valid dates is from noon on January 1st, 4713 B.C. forward. Internally, the
|
|
/// date calculations are done using Astronomical Julian Day numbers. The Astronomical Julian
|
|
/// Day number is defined as the number of days since noon on January 1st, 4713 B.C.
|
|
/// (also referred to as 12:00 on January 1, -4712).
|
|
/// NOTE: MS Excel actually has an error in the Serial Date calculations because it
|
|
/// errantly assumes 1900 is a leap year. The XDate calculations do not have this same
|
|
/// error. Therefore, XDate and Excel Date Serial values are 1 day different up until
|
|
/// the date value of 60 (in Excel, this is February 29th, 1900, and in XDate, this is
|
|
/// February 28th, 1900). At a value of 61 (March 1st, 1900) or greater, they agree with
|
|
/// eachother.
|
|
/// </remarks>
|
|
/// <author> John Champion </author>
|
|
/// <version> $Revision: 3.20 $ $Date: 2007/03/11 02:08:16 $ </version>
|
|
public struct XDate //: ICloneable
|
|
{
|
|
#region Fields & Constants
|
|
// =========================================================================
|
|
// Internal Variables
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// The actual date value in MS Excel format. This is the only data field in
|
|
/// the <see cref="XDate"/> struct.
|
|
/// </summary>
|
|
private double _xlDate;
|
|
|
|
/// <summary>
|
|
/// The Astronomical Julian Day number that corresponds to XL Date 0.0
|
|
/// </summary>
|
|
public const double XLDay1 = 2415018.5;
|
|
|
|
/// <summary>
|
|
/// The minimum valid Julian Day, which corresponds to January 1st, 4713 B.C.
|
|
/// </summary>
|
|
public const double JulDayMin = 0.0;
|
|
/// <summary>
|
|
/// The maximum valid Julian Day, which corresponds to December 31st, 9999 A.D.
|
|
/// </summary>
|
|
public const double JulDayMax = 5373483.5;
|
|
/// <summary>
|
|
/// The minimum valid Excel Day, which corresponds to January 1st, 4713 B.C.
|
|
/// </summary>
|
|
public const double XLDayMin = JulDayMin - XLDay1;
|
|
/// <summary>
|
|
/// The maximum valid Excel Day, which corresponds to December 31st, 9999 A.D.
|
|
/// </summary>
|
|
public const double XLDayMax = JulDayMax - XLDay1;
|
|
|
|
/// <summary>
|
|
/// The number of months in a year
|
|
/// </summary>
|
|
public const double MonthsPerYear = 12.0;
|
|
/// <summary>
|
|
/// The number of hours in a day
|
|
/// </summary>
|
|
public const double HoursPerDay = 24.0;
|
|
/// <summary>
|
|
/// The number of minutes in an hour
|
|
/// </summary>
|
|
public const double MinutesPerHour = 60.0;
|
|
/// <summary>
|
|
/// The number of seconds in a minute
|
|
/// </summary>
|
|
public const double SecondsPerMinute = 60.0;
|
|
/// <summary>
|
|
/// The number of minutes in a day
|
|
/// </summary>
|
|
public const double MinutesPerDay = 1440.0;
|
|
/// <summary>
|
|
/// The number of seconds in a day
|
|
/// </summary>
|
|
public const double SecondsPerDay = 86400.0;
|
|
/// <summary>
|
|
/// The number of milliseconds in a second
|
|
/// </summary>
|
|
public const double MillisecondsPerSecond = 1000.0;
|
|
/// <summary>
|
|
/// The number of milliseconds in a day
|
|
/// </summary>
|
|
public const double MillisecondsPerDay = 86400000.0;
|
|
/// <summary>
|
|
/// The default format string to be used in <see cref="ToString()"/> when
|
|
/// no format is provided
|
|
/// </summary>
|
|
// public const string DefaultFormatStr = "&d-&mmm-&yy &hh:&nn";
|
|
public const string DefaultFormatStr = "g";
|
|
#endregion
|
|
|
|
#region Constructors
|
|
// =========================================================================
|
|
// Constructors
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// Construct a date class from an XL date value.
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// An XL Date value in floating point double format
|
|
/// </param>
|
|
public XDate( double xlDate )
|
|
{
|
|
_xlDate = xlDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a date class from a <see cref="DateTime"/> struct.
|
|
/// </summary>
|
|
/// <param name="dateTime">
|
|
/// A <see cref="DateTime"/> struct containing the initial date information.
|
|
/// </param>
|
|
public XDate( DateTime dateTime )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( dateTime.Year, dateTime.Month,
|
|
dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second,
|
|
dateTime.Millisecond );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a date class from a calendar date (year, month, day). Assumes the time
|
|
/// of day is 00:00 hrs
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.
|
|
/// It is permissible to have day numbers outside of the 1-31 range,
|
|
/// which will rollover to the previous or next month and year.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August. It is permissible to have months outside of the 1-12 range,
|
|
/// which will rollover to the previous or next year.</param>
|
|
public XDate( int year, int month, int day )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( year, month, day, 0, 0, 0 );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a date class from a calendar date and time (year, month, day, hour, minute,
|
|
/// second).
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.
|
|
/// It is permissible to have day numbers outside of the 1-31 range,
|
|
/// which will rollover to the previous or next month and year.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August. It is permissible to have months outside of the 1-12 range,
|
|
/// which will rollover to the previous or next year.</param>
|
|
/// <param name="hour">An integer value for the hour of the day, e.g. 15.
|
|
/// It is permissible to have hour values outside the 0-23 range, which
|
|
/// will rollover to the previous or next day.</param>
|
|
/// <param name="minute">An integer value for the minute, e.g. 45.
|
|
/// It is permissible to have hour values outside the 0-59 range, which
|
|
/// will rollover to the previous or next hour.</param>
|
|
/// <param name="second">An integer value for the second, e.g. 35.
|
|
/// It is permissible to have second values outside the 0-59 range, which
|
|
/// will rollover to the previous or next minute.</param>
|
|
public XDate( int year, int month, int day, int hour, int minute, int second )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a date class from a calendar date and time (year, month, day, hour, minute,
|
|
/// second), where seconds is a <see cref="System.Double" /> value (allowing fractional seconds).
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.
|
|
/// It is permissible to have day numbers outside of the 1-31 range,
|
|
/// which will rollover to the previous or next month and year.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August. It is permissible to have months outside of the 1-12 range,
|
|
/// which will rollover to the previous or next year.</param>
|
|
/// <param name="hour">An integer value for the hour of the day, e.g. 15.
|
|
/// It is permissible to have hour values outside the 0-23 range, which
|
|
/// will rollover to the previous or next day.</param>
|
|
/// <param name="minute">An integer value for the minute, e.g. 45.
|
|
/// It is permissible to have hour values outside the 0-59 range, which
|
|
/// will rollover to the previous or next hour.</param>
|
|
/// <param name="second">A double value for the second, e.g. 35.75.
|
|
/// It is permissible to have second values outside the 0-59 range, which
|
|
/// will rollover to the previous or next minute.</param>
|
|
public XDate( int year, int month, int day, int hour, int minute, double second )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Construct a date class from a calendar date and time (year, month, day, hour, minute,
|
|
/// second, millisecond).
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.
|
|
/// It is permissible to have day numbers outside of the 1-31 range,
|
|
/// which will rollover to the previous or next month and year.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August. It is permissible to have months outside of the 1-12 range,
|
|
/// which will rollover to the previous or next year.</param>
|
|
/// <param name="hour">An integer value for the hour of the day, e.g. 15.
|
|
/// It is permissible to have hour values outside the 0-23 range, which
|
|
/// will rollover to the previous or next day.</param>
|
|
/// <param name="minute">An integer value for the minute, e.g. 45.
|
|
/// It is permissible to have hour values outside the 0-59 range, which
|
|
/// will rollover to the previous or next hour.</param>
|
|
/// <param name="second">An integer value for the second, e.g. 35.
|
|
/// It is permissible to have second values outside the 0-59 range, which
|
|
/// will rollover to the previous or next minute.</param>
|
|
/// <param name="millisecond">An integer value for the millisecond, e.g. 632.
|
|
/// It is permissible to have millisecond values outside the 0-999 range, which
|
|
/// will rollover to the previous or next second.</param>
|
|
public XDate( int year, int month, int day, int hour, int minute, int second, int millisecond )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second, millisecond );
|
|
}
|
|
|
|
/// <summary>
|
|
/// The Copy Constructor
|
|
/// </summary>
|
|
/// <param name="rhs">The GraphPane object from which to copy</param>
|
|
public XDate( XDate rhs )
|
|
{
|
|
_xlDate = rhs._xlDate;
|
|
}
|
|
/*
|
|
/// <summary>
|
|
/// Implement the <see cref="ICloneable" /> interface in a typesafe manner by just
|
|
/// calling the typed version of <see cref="Clone" />
|
|
/// </summary>
|
|
/// <returns>A deep copy of this object</returns>
|
|
object ICloneable.Clone()
|
|
{
|
|
return this.Clone();
|
|
}
|
|
|
|
/// <summary>
|
|
/// Typesafe, deep-copy clone method.
|
|
/// </summary>
|
|
/// <returns>A new, independent copy of this class</returns>
|
|
public XDate Clone()
|
|
{
|
|
return new XDate( this );
|
|
}
|
|
*/
|
|
|
|
#endregion
|
|
|
|
#region Properties
|
|
// =========================================================================
|
|
// Properties
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// Gets or sets the date value for this item in MS Excel format.
|
|
/// </summary>
|
|
public double XLDate
|
|
{
|
|
get { return _xlDate; }
|
|
set { _xlDate = value; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if this <see cref="XDate" /> struct is in the valid date range
|
|
/// </summary>
|
|
public bool IsValidDate
|
|
{
|
|
get { return _xlDate >= XLDayMin && _xlDate <= XLDayMax; }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the date value for this item in .Net DateTime format.
|
|
/// </summary>
|
|
public DateTime DateTime
|
|
{
|
|
get { return XLDateToDateTime( _xlDate ); }
|
|
set { _xlDate = DateTimeToXLDate( value ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the date value for this item in Julain day format. This is the
|
|
/// Astronomical Julian Day number, so a value of 0.0 corresponds to noon GMT on
|
|
/// January 1st, -4712. Thus, Julian Day number 2,400,000.0 corresponds to
|
|
/// noon GMT on November 16, 1858.
|
|
/// </summary>
|
|
public double JulianDay
|
|
{
|
|
get { return XLDateToJulianDay( _xlDate ); }
|
|
set { _xlDate = JulianDayToXLDate( value ); }
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the decimal year number (i.e., 1997.345) corresponding to this item.
|
|
/// </summary>
|
|
public double DecimalYear
|
|
{
|
|
get { return XLDateToDecimalYear( _xlDate ); }
|
|
set { _xlDate = DecimalYearToXLDate( value ); }
|
|
}
|
|
#endregion
|
|
|
|
#region Get/Set Date Methods
|
|
|
|
/// <summary>
|
|
/// Returns true if the specified date value is in the valid range
|
|
/// </summary>
|
|
/// <param name="xlDate">The XL date value to be verified for validity</param>
|
|
/// <returns>true for a valid date, false otherwise</returns>
|
|
private static bool CheckValidDate( double xlDate )
|
|
{
|
|
return xlDate >= XLDayMin && xlDate <= XLDayMax;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Take the specified date, and bound it to the valid date range for the XDate struct.
|
|
/// </summary>
|
|
/// <param name="xlDate">The date to be bounded</param>
|
|
/// <returns>An XLDate value that lies between the minimum and maximum valid date ranges
|
|
/// (see <see cref="XLDayMin" /> and <see cref="XLDayMax" />)</returns>
|
|
public static double MakeValidDate( double xlDate )
|
|
{
|
|
if ( xlDate < XLDayMin )
|
|
xlDate = XLDayMin;
|
|
if ( xlDate > XLDayMax )
|
|
xlDate = XLDayMax;
|
|
return xlDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the calendar date (year, month, day) corresponding to this instance.
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August.</param>
|
|
public void GetDate( out int year, out int month, out int day )
|
|
{
|
|
int hour, minute, second;
|
|
|
|
XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the calendar date (year, month, day) of this instance.
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August.</param>
|
|
public void SetDate( int year, int month, int day )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( year, month, day, 0, 0, 0 );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the calendar date (year, month, day, hour, minute, second) corresponding
|
|
/// to this instance.
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August.</param>
|
|
/// <param name="hour">An integer value for the hour of the day, e.g. 15.</param>
|
|
/// <param name="minute">An integer value for the minute, e.g. 45.</param>
|
|
/// <param name="second">An integer value for the second, e.g. 35.</param>
|
|
public void GetDate( out int year, out int month, out int day,
|
|
out int hour, out int minute, out int second )
|
|
{
|
|
XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Set the calendar date (year, month, day, hour, minute, second) of this instance.
|
|
/// </summary>
|
|
/// <param name="year">An integer value for the year, e.g., 1995.</param>
|
|
/// <param name="day">An integer value for the day of the month, e.g., 23.</param>
|
|
/// <param name="month">An integer value for the month of the year, e.g.,
|
|
/// 8 for August.</param>
|
|
/// <param name="hour">An integer value for the hour of the day, e.g. 15.</param>
|
|
/// <param name="minute">An integer value for the minute, e.g. 45.</param>
|
|
/// <param name="second">An integer value for the second, e.g. 35.</param>
|
|
public void SetDate( int year, int month, int day, int hour, int minute, int second )
|
|
{
|
|
_xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Get the day of year value (241.345 means the 241st day of the year)
|
|
/// corresponding to this instance.
|
|
/// </summary>
|
|
/// <returns>The day of the year in floating point double format.</returns>
|
|
public double GetDayOfYear()
|
|
{
|
|
return XLDateToDayOfYear( _xlDate );
|
|
}
|
|
#endregion
|
|
|
|
#region Date Conversion Methods
|
|
// =========================================================================
|
|
// Conversion Routines
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second),
|
|
/// first normalizing all input data values.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The Calendar date is always based on the Gregorian Calendar. Note that the Gregorian calendar is really
|
|
/// only valid from October 15, 1582 forward. The countries that adopted the Gregorian calendar
|
|
/// first did so on October 4, 1582, so that the next day was October 15, 1582. Prior to that time
|
|
/// the Julian Calendar was used. However, Prior to March 1, 4 AD the treatment of leap years was
|
|
/// inconsistent, and prior to 45 BC the Julian Calendar did not exist. The <see cref="XDate"/>
|
|
/// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The
|
|
/// <see cref="ToString(double,string)"/> method will just append a "(BC)" notation to the end of any dates
|
|
/// prior to 1 AD, since the <see cref="DateTime"/> struct throws an exception when formatting earlier dates.
|
|
/// </remarks>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The integer millisecond value (e.g., 374 for 374 milliseconds past the second).
|
|
/// </param>
|
|
/// <returns>The corresponding XL date, expressed in double floating point format</returns>
|
|
public static double CalendarDateToXLDate( int year, int month, int day,
|
|
int hour, int minute, int second, int millisecond )
|
|
{
|
|
// Normalize the data to allow for negative and out of range values
|
|
// In this way, setting month to zero would be December of the previous year,
|
|
// setting hour to 24 would be the first hour of the next day, etc.
|
|
//double dsec = second + (double) millisecond / MillisecondsPerSecond;
|
|
double ms = millisecond;
|
|
NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute, ref second,
|
|
ref ms );
|
|
|
|
return _CalendarDateToXLDate( year, month, day, hour, minute, second, ms );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second),
|
|
/// first normalizing all input data values.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The Calendar date is always based on the Gregorian Calendar. Note that the Gregorian calendar is really
|
|
/// only valid from October 15, 1582 forward. The countries that adopted the Gregorian calendar
|
|
/// first did so on October 4, 1582, so that the next day was October 15, 1582. Prior to that time
|
|
/// the Julian Calendar was used. However, Prior to March 1, 4 AD the treatment of leap years was
|
|
/// inconsistent, and prior to 45 BC the Julian Calendar did not exist. The <see cref="XDate"/>
|
|
/// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The
|
|
/// <see cref="ToString(double,string)"/> method will just append a "(BC)" notation to the end of any dates
|
|
/// prior to 1 AD, since the <see cref="DateTime"/> struct throws an exception when formatting earlier dates.
|
|
/// </remarks>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <returns>The corresponding XL date, expressed in double floating point format</returns>
|
|
public static double CalendarDateToXLDate( int year, int month, int day,
|
|
int hour, int minute, int second )
|
|
{
|
|
// Normalize the data to allow for negative and out of range values
|
|
// In this way, setting month to zero would be December of the previous year,
|
|
// setting hour to 24 would be the first hour of the next day, etc.
|
|
double ms = 0;
|
|
NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute,
|
|
ref second, ref ms );
|
|
|
|
return _CalendarDateToXLDate( year, month, day, hour, minute, second, ms );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second),
|
|
/// first normalizing all input data values. The seconds value is a double type, allowing fractional
|
|
/// seconds.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The Calendar date is always based on the Gregorian Calendar. Note that the Gregorian calendar is really
|
|
/// only valid from October 15, 1582 forward. The countries that adopted the Gregorian calendar
|
|
/// first did so on October 4, 1582, so that the next day was October 15, 1582. Prior to that time
|
|
/// the Julian Calendar was used. However, Prior to March 1, 4 AD the treatment of leap years was
|
|
/// inconsistent, and prior to 45 BC the Julian Calendar did not exist. The <see cref="XDate"/>
|
|
/// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The
|
|
/// <see cref="ToString(double,string)"/> method will just append a "(BC)" notation to the end of any dates
|
|
/// prior to 1 AD, since the <see cref="DateTime"/> struct throws an exception when formatting earlier dates.
|
|
/// </remarks>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The double second value (e.g., 42.3 for 42.3 seconds past the minute).
|
|
/// </param>
|
|
/// <returns>The corresponding XL date, expressed in double floating point format</returns>
|
|
public static double CalendarDateToXLDate( int year, int month, int day,
|
|
int hour, int minute, double second )
|
|
{
|
|
// Normalize the data to allow for negative and out of range values
|
|
// In this way, setting month to zero would be December of the previous year,
|
|
// setting hour to 24 would be the first hour of the next day, etc.
|
|
int sec = (int)second;
|
|
double ms = ( second - sec ) * MillisecondsPerSecond;
|
|
NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute, ref sec,
|
|
ref ms );
|
|
|
|
return _CalendarDateToXLDate( year, month, day, hour, minute, sec, ms );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an Astronomical Julian Day number from the specified Calendar date
|
|
/// (year, month, day, hour, minute, second), first normalizing all input data values
|
|
/// </summary>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <returns>The corresponding Astronomical Julian Day number, expressed in double
|
|
/// floating point format</returns>
|
|
public static double CalendarDateToJulianDay( int year, int month, int day,
|
|
int hour, int minute, int second )
|
|
{
|
|
// Normalize the data to allow for negative and out of range values
|
|
// In this way, setting month to zero would be December of the previous year,
|
|
// setting hour to 24 would be the first hour of the next day, etc.
|
|
double ms = 0;
|
|
NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute,
|
|
ref second, ref ms );
|
|
|
|
return _CalendarDateToJulianDay( year, month, day, hour, minute, second, ms );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an Astronomical Julian Day number from the specified Calendar date
|
|
/// (year, month, day, hour, minute, second), first normalizing all input data values
|
|
/// </summary>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The integer second value (e.g., 325 for 325 milliseconds past the minute).
|
|
/// </param>
|
|
/// <returns>The corresponding Astronomical Julian Day number, expressed in double
|
|
/// floating point format</returns>
|
|
public static double CalendarDateToJulianDay( int year, int month, int day,
|
|
int hour, int minute, int second, int millisecond )
|
|
{
|
|
// Normalize the data to allow for negative and out of range values
|
|
// In this way, setting month to zero would be December of the previous year,
|
|
// setting hour to 24 would be the first hour of the next day, etc.
|
|
double ms = millisecond;
|
|
|
|
NormalizeCalendarDate( ref year, ref month, ref day, ref hour, ref minute,
|
|
ref second, ref ms );
|
|
|
|
return _CalendarDateToJulianDay( year, month, day, hour, minute, second, ms );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Normalize a set of Calendar date values (year, month, day, hour, minute, second) to make sure
|
|
/// that month is between 1 and 12, hour is between 0 and 23, etc.
|
|
/// </summary>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second).
|
|
/// </param>
|
|
private static void NormalizeCalendarDate( ref int year, ref int month, ref int day,
|
|
ref int hour, ref int minute, ref int second,
|
|
ref double millisecond )
|
|
{
|
|
// Normalize the data to allow for negative and out of range values
|
|
// In this way, setting month to zero would be December of the previous year,
|
|
// setting hour to 24 would be the first hour of the next day, etc.
|
|
|
|
// Normalize the milliseconds and carry over to seconds
|
|
int carry = (int)Math.Floor( millisecond / MillisecondsPerSecond );
|
|
millisecond -= carry * (int)MillisecondsPerSecond;
|
|
second += carry;
|
|
|
|
// Normalize the seconds and carry over to minutes
|
|
carry = (int)Math.Floor( second / SecondsPerMinute );
|
|
second -= carry * (int)SecondsPerMinute;
|
|
minute += carry;
|
|
|
|
// Normalize the minutes and carry over to hours
|
|
carry = (int) Math.Floor( (double) minute / MinutesPerHour );
|
|
minute -= carry * (int) MinutesPerHour;
|
|
hour += carry;
|
|
|
|
// Normalize the hours and carry over to days
|
|
carry = (int) Math.Floor( (double) hour / HoursPerDay );
|
|
hour -= carry * (int) HoursPerDay;
|
|
day += carry;
|
|
|
|
// Normalize the months and carry over to years
|
|
carry = (int) Math.Floor( (double) month / MonthsPerYear );
|
|
month -= carry * (int) MonthsPerYear;
|
|
year += carry;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an XL date from the specified Calendar date (year, month, day, hour, minute, second).
|
|
/// This is the internal trusted version, where all values are assumed to be legitimate
|
|
/// ( month is between 1 and 12, minute is between 0 and 59, etc. )
|
|
/// </summary>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second).
|
|
/// </param>
|
|
/// <returns>The corresponding XL date, expressed in double floating point format</returns>
|
|
private static double _CalendarDateToXLDate( int year, int month, int day, int hour,
|
|
int minute, int second, double millisecond )
|
|
{
|
|
return JulianDayToXLDate( _CalendarDateToJulianDay( year, month, day, hour, minute,
|
|
second, millisecond ) );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an Astronomical Julian Day Number from the specified Calendar date
|
|
/// (year, month, day, hour, minute, second).
|
|
/// This is the internal trusted version, where all values are assumed to be legitimate
|
|
/// ( month is between 1 and 12, minute is between 0 and 59, etc. )
|
|
/// </summary>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second).
|
|
/// </param>
|
|
/// <returns>The corresponding Astronomical Julian Day number, expressed in double
|
|
/// floating point format</returns>
|
|
private static double _CalendarDateToJulianDay( int year, int month, int day, int hour,
|
|
int minute, int second, double millisecond )
|
|
{
|
|
// Taken from http://www.srrb.noaa.gov/highlights/sunrise/program.txt
|
|
// routine calcJD()
|
|
|
|
if ( month <= 2 )
|
|
{
|
|
year -= 1;
|
|
month += 12;
|
|
}
|
|
|
|
double A = Math.Floor( (double) year / 100.0 );
|
|
double B = 2 - A + Math.Floor( A / 4.0 );
|
|
|
|
return Math.Floor( 365.25 * ( (double) year + 4716.0 ) ) +
|
|
Math.Floor( 30.6001 * (double) ( month + 1 ) ) +
|
|
(double) day + B - 1524.5 +
|
|
hour / HoursPerDay + minute / MinutesPerDay + second / SecondsPerDay +
|
|
millisecond / MillisecondsPerDay;
|
|
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
|
|
/// the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
public static void XLDateToCalendarDate( double xlDate, out int year, out int month,
|
|
out int day, out int hour, out int minute, out int second )
|
|
{
|
|
double jDay = XLDateToJulianDay( xlDate );
|
|
|
|
JulianDayToCalendarDate( jDay, out year, out month, out day, out hour,
|
|
out minute, out second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
|
|
/// the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The integer millisecond value (e.g., 325 for 325 milliseconds past the second).
|
|
/// </param>
|
|
public static void XLDateToCalendarDate( double xlDate, out int year, out int month,
|
|
out int day, out int hour, out int minute, out int second, out int millisecond )
|
|
{
|
|
double jDay = XLDateToJulianDay( xlDate );
|
|
|
|
double ms;
|
|
JulianDayToCalendarDate( jDay, out year, out month, out day, out hour,
|
|
out minute, out second, out ms );
|
|
millisecond = (int)ms;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
|
|
/// the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The double second value (e.g., 42.3 for 42.3 seconds past the minute).
|
|
/// </param>
|
|
public static void XLDateToCalendarDate( double xlDate, out int year, out int month,
|
|
out int day, out int hour, out int minute, out double second )
|
|
{
|
|
double jDay = XLDateToJulianDay( xlDate );
|
|
|
|
JulianDayToCalendarDate( jDay, out year, out month, out day, out hour,
|
|
out minute, out second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
|
|
/// the Astronomical Julian Day number
|
|
/// </summary>
|
|
/// <param name="jDay">
|
|
/// The Astronomical Julian Day number to be converted
|
|
/// </param>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
public static void JulianDayToCalendarDate( double jDay, out int year, out int month,
|
|
out int day, out int hour, out int minute, out int second )
|
|
{
|
|
double ms = 0;
|
|
|
|
JulianDayToCalendarDate( jDay, out year, out month,
|
|
out day, out hour, out minute, out second, out ms );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
|
|
/// the Astronomical Julian Day number
|
|
/// </summary>
|
|
/// <param name="jDay">
|
|
/// The Astronomical Julian Day number to be converted
|
|
/// </param>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The double second value (e.g., 42.3 for 42.3 seconds past the minute).
|
|
/// </param>
|
|
public static void JulianDayToCalendarDate( double jDay, out int year, out int month,
|
|
out int day, out int hour, out int minute, out double second )
|
|
{
|
|
int sec;
|
|
double ms;
|
|
|
|
JulianDayToCalendarDate( jDay, out year, out month,
|
|
out day, out hour, out minute, out sec, out ms );
|
|
|
|
second = sec + ms / MillisecondsPerSecond;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to
|
|
/// the Astronomical Julian Day number
|
|
/// </summary>
|
|
/// <param name="jDay">
|
|
/// The Astronomical Julian Day number to be converted
|
|
/// </param>
|
|
/// <param name="year">
|
|
/// The integer year value (e.g., 1994).
|
|
/// </param>
|
|
/// <param name="month">
|
|
/// The integer month value (e.g., 7 for July).
|
|
/// </param>
|
|
/// <param name="day">
|
|
/// The integer day value (e.g., 19 for the 19th day of the month).
|
|
/// </param>
|
|
/// <param name="hour">
|
|
/// The integer hour value (e.g., 14 for 2:00 pm).
|
|
/// </param>
|
|
/// <param name="minute">
|
|
/// The integer minute value (e.g., 35 for 35 minutes past the hour).
|
|
/// </param>
|
|
/// <param name="second">
|
|
/// The integer second value (e.g., 42 for 42 seconds past the minute).
|
|
/// </param>
|
|
/// <param name="millisecond">
|
|
/// The <see cref="System.Double" /> millisecond value (e.g., 342.5 for 342.5 milliseconds past
|
|
/// the second).
|
|
/// </param>
|
|
public static void JulianDayToCalendarDate( double jDay, out int year, out int month,
|
|
out int day, out int hour, out int minute, out int second, out double millisecond )
|
|
{
|
|
// add 5 ten-thousandths of a second to the day fraction to avoid roundoff errors
|
|
jDay += 0.0005 / SecondsPerDay;
|
|
|
|
double z = Math.Floor( jDay + 0.5);
|
|
double f = jDay + 0.5 - z;
|
|
|
|
double alpha = Math.Floor( ( z - 1867216.25 ) / 36524.25 );
|
|
double A = z + 1.0 + alpha - Math.Floor( alpha / 4 );
|
|
double B = A + 1524.0;
|
|
double C = Math.Floor( ( B - 122.1 ) / 365.25 );
|
|
double D = Math.Floor( 365.25 * C );
|
|
double E = Math.Floor( ( B - D ) / 30.6001 );
|
|
|
|
day = (int) Math.Floor( B - D - Math.Floor( 30.6001 * E ) + f );
|
|
month = (int) ( ( E < 14.0 ) ? E - 1.0 : E - 13.0 );
|
|
year = (int) ( ( month > 2 ) ? C - 4716 : C - 4715 );
|
|
|
|
double fday = ( jDay - 0.5 ) - Math.Floor( jDay - 0.5 );
|
|
|
|
fday = ( fday - (long) fday ) * HoursPerDay;
|
|
hour = (int) fday;
|
|
fday = ( fday - (long) fday ) * MinutesPerHour;
|
|
minute = (int) fday;
|
|
fday = ( fday - (long) fday ) * SecondsPerMinute;
|
|
second = (int) fday;
|
|
fday = ( fday - (long) fday ) * MillisecondsPerSecond;
|
|
millisecond = fday;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an Astronomical Julian Day number corresponding to the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding Astronomical Julian Day number, expressed in double
|
|
/// floating point format</returns>
|
|
public static double XLDateToJulianDay( double xlDate )
|
|
{
|
|
return xlDate + XLDay1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate an XL Date corresponding to the specified Astronomical Julian Day number
|
|
/// </summary>
|
|
/// <param name="jDay">
|
|
/// The Astronomical Julian Day number in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding XL Date, expressed in double
|
|
/// floating point format</returns>
|
|
public static double JulianDayToXLDate( double jDay )
|
|
{
|
|
return jDay - XLDay1;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a decimal year value (e.g., 1994.6523) corresponding to the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding decimal year value, expressed in double
|
|
/// floating point format</returns>
|
|
public static double XLDateToDecimalYear( double xlDate )
|
|
{
|
|
int year, month, day, hour, minute, second;
|
|
|
|
XLDateToCalendarDate( xlDate, out year, out month, out day, out hour, out minute, out second );
|
|
|
|
double jDay1 = CalendarDateToJulianDay( year, 1, 1, 0, 0, 0 );
|
|
double jDay2 = CalendarDateToJulianDay( year + 1, 1, 1, 0, 0, 0 );
|
|
double jDayMid = CalendarDateToJulianDay( year, month, day, hour, minute, second );
|
|
|
|
|
|
return (double) year + ( jDayMid - jDay1 ) / ( jDay2 - jDay1 );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a decimal year value (e.g., 1994.6523) corresponding to the specified XL date
|
|
/// </summary>
|
|
/// <param name="yearDec">
|
|
/// The decimal year value in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding XL Date, expressed in double
|
|
/// floating point format</returns>
|
|
public static double DecimalYearToXLDate( double yearDec )
|
|
{
|
|
int year = (int) yearDec;
|
|
|
|
double jDay1 = CalendarDateToJulianDay( year, 1, 1, 0, 0, 0 );
|
|
double jDay2 = CalendarDateToJulianDay( year + 1, 1, 1, 0, 0, 0 );
|
|
|
|
return JulianDayToXLDate( ( yearDec - (double) year ) * ( jDay2 - jDay1 ) + jDay1 );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a day-of-year value (e.g., 241.543 corresponds to the 241st day of the year)
|
|
/// corresponding to the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding day-of-year (DoY) value, expressed in double
|
|
/// floating point format</returns>
|
|
public static double XLDateToDayOfYear( double xlDate )
|
|
{
|
|
int year, month, day, hour, minute, second;
|
|
XLDateToCalendarDate( xlDate, out year, out month, out day,
|
|
out hour, out minute, out second );
|
|
return XLDateToJulianDay( xlDate ) - CalendarDateToJulianDay( year, 1, 1, 0, 0, 0 ) + 1.0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Calculate a day-of-week value (e.g., Sun=0, Mon=1, Tue=2, etc.)
|
|
/// corresponding to the specified XL date
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding day-of-week (DoW) value, expressed in integer format</returns>
|
|
public static int XLDateToDayOfWeek( double xlDate )
|
|
{
|
|
return (int) ( XLDateToJulianDay( xlDate ) + 1.5 ) % 7;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert an XL date format to a .Net DateTime struct
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value in floating point double format.
|
|
/// </param>
|
|
/// <returns>The corresponding XL Date, expressed in double
|
|
/// floating point format</returns>
|
|
/// <returns>The corresponding date in the form of a .Net DateTime struct</returns>
|
|
public static DateTime XLDateToDateTime( double xlDate )
|
|
{
|
|
int year, month, day, hour, minute, second;
|
|
XLDateToCalendarDate( xlDate, out year, out month, out day,
|
|
out hour, out minute, out second );
|
|
return new DateTime( year, month, day, hour, minute, second );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Convert a .Net DateTime struct to an XL Format date
|
|
/// </summary>
|
|
/// <param name="dt">
|
|
/// The date value in the form of a .Net DateTime struct
|
|
/// </param>
|
|
/// <returns>The corresponding XL Date, expressed in double
|
|
/// floating point format</returns>
|
|
public static double DateTimeToXLDate( DateTime dt )
|
|
{
|
|
return CalendarDateToXLDate( dt.Year, dt.Month, dt.Day, dt.Hour, dt.Minute, dt.Second );
|
|
}
|
|
#endregion
|
|
|
|
#region Date Math Methods
|
|
// =========================================================================
|
|
// Math Routines
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// Add the specified number of milliseconds (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dMilliseconds">
|
|
/// The incremental number of milliseconds (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddMilliseconds( double dMilliseconds )
|
|
{
|
|
_xlDate += dMilliseconds / MillisecondsPerDay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified number of seconds (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dSeconds">
|
|
/// The incremental number of seconds (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddSeconds( double dSeconds )
|
|
{
|
|
_xlDate += dSeconds / SecondsPerDay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified number of minutes (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dMinutes">
|
|
/// The incremental number of minutes (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddMinutes( double dMinutes )
|
|
{
|
|
_xlDate += dMinutes / MinutesPerDay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified number of hours (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dHours">
|
|
/// The incremental number of hours (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddHours( double dHours )
|
|
{
|
|
_xlDate += dHours / HoursPerDay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified number of days (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dDays">
|
|
/// The incremental number of days (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddDays( double dDays )
|
|
{
|
|
_xlDate += dDays;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified number of Months (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dMonths">
|
|
/// The incremental number of months (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddMonths( double dMonths )
|
|
{
|
|
int iMon = (int) dMonths;
|
|
double monFrac = Math.Abs( dMonths - (double) iMon );
|
|
int sMon = Math.Sign( dMonths );
|
|
|
|
int year, month, day, hour, minute, second;
|
|
|
|
XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
|
|
if ( iMon != 0 )
|
|
{
|
|
month += iMon;
|
|
_xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
|
|
}
|
|
|
|
if ( sMon != 0 )
|
|
{
|
|
double xlDate2 = CalendarDateToXLDate( year, month+sMon, day, hour, minute, second );
|
|
_xlDate += (xlDate2 - _xlDate) * monFrac;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Add the specified number of years (can be fractional) to the current XDate instance.
|
|
/// </summary>
|
|
/// <param name="dYears">
|
|
/// The incremental number of years (negative or positive) in floating point double format.
|
|
/// </param>
|
|
public void AddYears( double dYears )
|
|
{
|
|
int iYear = (int) dYears;
|
|
double yearFrac = Math.Abs( dYears - (double) iYear );
|
|
int sYear = Math.Sign( dYears );
|
|
|
|
int year, month, day, hour, minute, second;
|
|
|
|
XLDateToCalendarDate( _xlDate, out year, out month, out day, out hour, out minute, out second );
|
|
if ( iYear != 0 )
|
|
{
|
|
year += iYear;
|
|
_xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second );
|
|
}
|
|
|
|
if ( sYear != 0 )
|
|
{
|
|
double xlDate2 = CalendarDateToXLDate( year+sYear, month, day, hour, minute, second );
|
|
_xlDate += (xlDate2 - _xlDate) * yearFrac;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Operator Overload Methods
|
|
// =========================================================================
|
|
// Operator Overloads
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// '-' operator overload. When two XDates are subtracted, the number of days between dates
|
|
/// is returned.
|
|
/// </summary>
|
|
/// <param name="lhs">The left-hand-side of the '-' operator (an XDate class)</param>
|
|
/// <param name="rhs">The right-hand-side of the '-' operator (an XDate class)</param>
|
|
/// <returns>The days between dates, expressed as a floating point double</returns>
|
|
public static double operator -( XDate lhs, XDate rhs )
|
|
{
|
|
return lhs.XLDate - rhs.XLDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// '-' operator overload. When a double value is subtracted from an XDate, the result is a
|
|
/// new XDate with the number of days subtracted.
|
|
/// </summary>
|
|
/// <param name="lhs">The left-hand-side of the '-' operator (an XDate class)</param>
|
|
/// <param name="rhs">The right-hand-side of the '-' operator (a double value)</param>
|
|
/// <returns>An XDate with the rhs number of days subtracted</returns>
|
|
public static XDate operator -( XDate lhs, double rhs )
|
|
{
|
|
lhs._xlDate -= rhs;
|
|
return lhs;
|
|
}
|
|
|
|
/// <summary>
|
|
/// '+' operator overload. When a double value is added to an XDate, the result is a
|
|
/// new XDate with the number of days added.
|
|
/// </summary>
|
|
/// <param name="lhs">The left-hand-side of the '-' operator (an XDate class)</param>
|
|
/// <param name="rhs">The right-hand-side of the '+' operator (a double value)</param>
|
|
/// <returns>An XDate with the rhs number of days added</returns>
|
|
public static XDate operator +( XDate lhs, double rhs )
|
|
{
|
|
lhs._xlDate += rhs;
|
|
return lhs;
|
|
}
|
|
|
|
/// <summary>
|
|
/// '++' operator overload. Increment the date by one day.
|
|
/// </summary>
|
|
/// <param name="xDate">The XDate struct on which to operate</param>
|
|
/// <returns>An XDate one day later than the specified date</returns>
|
|
public static XDate operator ++( XDate xDate )
|
|
{
|
|
xDate._xlDate += 1.0;
|
|
return xDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// '--' operator overload. Decrement the date by one day.
|
|
/// </summary>
|
|
/// <param name="xDate">The XDate struct on which to operate</param>
|
|
/// <returns>An XDate one day prior to the specified date</returns>
|
|
public static XDate operator --( XDate xDate )
|
|
{
|
|
xDate._xlDate -= 1.0;
|
|
return xDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implicit conversion from XDate to double (an XL Date).
|
|
/// </summary>
|
|
/// <param name="xDate">The XDate struct on which to operate</param>
|
|
/// <returns>A double floating point value representing the XL Date</returns>
|
|
public static implicit operator double( XDate xDate )
|
|
{
|
|
return xDate._xlDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implicit conversion from XDate to float (an XL Date).
|
|
/// </summary>
|
|
/// <param name="xDate">The XDate struct on which to operate</param>
|
|
/// <returns>A double floating point value representing the XL Date</returns>
|
|
public static implicit operator float( XDate xDate )
|
|
{
|
|
return (float) xDate._xlDate;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implicit conversion from double (an XL Date) to XDate.
|
|
/// </summary>
|
|
/// <param name="xlDate">The XDate struct on which to operate</param>
|
|
/// <returns>An XDate struct representing the specified xlDate value.</returns>
|
|
public static implicit operator XDate( double xlDate )
|
|
{
|
|
return new XDate( xlDate );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implicit conversion from XDate to <see cref="DateTime"/>.
|
|
/// </summary>
|
|
/// <param name="xDate">The XDate struct on which to operate</param>
|
|
/// <returns>A <see cref="DateTime"/> struct representing the specified xDate value.</returns>
|
|
public static implicit operator DateTime( XDate xDate )
|
|
{
|
|
|
|
return XLDateToDateTime( xDate );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Implicit conversion from <see cref="DateTime"/> to <see cref="XDate"/>.
|
|
/// </summary>
|
|
/// <param name="dt">The <see cref="DateTime"/> struct on which to operate</param>
|
|
/// <returns>An <see cref="XDate"/> struct representing the specified DateTime value.</returns>
|
|
public static implicit operator XDate( DateTime dt )
|
|
{
|
|
|
|
return new XDate( DateTimeToXLDate( dt ) );
|
|
}
|
|
#endregion
|
|
|
|
#region General Overrides
|
|
// =========================================================================
|
|
// System Stuff
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// Tests whether <param>obj</param> is either an <see cref="XDate"/> structure or
|
|
/// a double floating point value that is equal to the same date as this <c>XDate</c>
|
|
/// struct instance.
|
|
/// </summary>
|
|
/// <param name="obj">The object to compare for equality with this XDate instance.
|
|
/// This object should be either a type XDate or type double.</param>
|
|
/// <returns>Returns <c>true</c> if <param>obj</param> is the same date as this
|
|
/// instance; otherwise, <c>false</c></returns>
|
|
public override bool Equals( object obj )
|
|
{
|
|
if ( obj is XDate )
|
|
{
|
|
return ((XDate) obj)._xlDate == _xlDate;
|
|
}
|
|
else if ( obj is double )
|
|
{
|
|
return ((double) obj) == _xlDate;
|
|
}
|
|
else
|
|
return false;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns the hash code for this <see cref="XDate"/> structure. In this case, the
|
|
/// hash code is simply the equivalent hash code for the floating point double date value.
|
|
/// </summary>
|
|
/// <returns>An integer representing the hash code for this XDate value</returns>
|
|
public override int GetHashCode()
|
|
{
|
|
return _xlDate.GetHashCode();
|
|
}
|
|
#endregion
|
|
|
|
#region String Format Conversion Methods
|
|
// =========================================================================
|
|
// String Formatting Routines
|
|
// =========================================================================
|
|
|
|
/// <summary>
|
|
/// Format this XDate value using the default format string (<see cref="DefaultFormatStr"/>).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The formatting is done using the <see cref="DateTime"/> <see cref="System.DateTime.ToString(string)"/>
|
|
/// method in order to provide full localization capability. The DateTime struct is limited to
|
|
/// dates from 1 AD onward. However, all calendar dates in <see cref="XDate"/> and <see cref="DateTime"/>
|
|
/// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
|
|
/// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
|
|
/// really dates that would have been, had the Gregorian calendar existed. In order to avoid
|
|
/// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
|
|
/// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
|
|
/// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
|
|
/// </remarks>
|
|
/// <param name="xlDate">
|
|
/// The XL date value to be formatted in floating point double format.
|
|
/// </param>
|
|
/// <returns>A string representation of the date</returns>
|
|
public string ToString( double xlDate )
|
|
{
|
|
return ToString( xlDate, DefaultFormatStr );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Format this XDate value using the default format string (see cref="DefaultFormatStr"/>).
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The formatting is done using the <see cref="DateTime" />
|
|
/// <see cref="System.DateTime.ToString(String)" />
|
|
/// method in order to provide full localization capability. The DateTime struct is limited to
|
|
/// dates from 1 AD onward. However, all calendar dates in <see cref="XDate" /> and
|
|
/// <see cref="DateTime" />
|
|
/// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
|
|
/// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
|
|
/// really dates that would have been, had the Gregorian calendar existed. In order to avoid
|
|
/// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
|
|
/// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
|
|
/// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
|
|
/// </remarks>
|
|
/// <returns>A string representation of the date</returns>
|
|
public override string ToString()
|
|
{
|
|
return ToString( _xlDate, DefaultFormatStr );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Format this XL Date value using the specified format string. The format
|
|
/// string is specified according to the <see cref="DateTime"/> class.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The formatting is done using the <see cref="DateTime" />
|
|
/// <see cref="System.DateTime.ToString(String)" />
|
|
/// method in order to provide full localization capability. The DateTime struct is limited to
|
|
/// dates from 1 AD onward. However, all calendar dates in <see cref="XDate" /> and
|
|
/// <see cref="DateTime" />
|
|
/// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
|
|
/// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
|
|
/// really dates that would have been, had the Gregorian calendar existed. In order to avoid
|
|
/// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
|
|
/// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
|
|
/// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
|
|
/// </remarks>
|
|
/// <param name="fmtStr">
|
|
/// The formatting string to be used for the date. See
|
|
/// <see cref="System.Globalization.DateTimeFormatInfo" />
|
|
/// class for a list of the format types available.</param>
|
|
/// <returns>A string representation of the date</returns>
|
|
public string ToString( string fmtStr )
|
|
{
|
|
return ToString( this.XLDate, fmtStr );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Format the specified XL Date value using the specified format string. The format
|
|
/// string is specified according to the <see cref="DateTime" /> class.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// The formatting is done using the <see cref="DateTime" />
|
|
/// <see cref="System.DateTime.ToString(String)" />
|
|
/// method in order to provide full localization capability. The DateTime struct is limited to
|
|
/// dates from 1 AD onward. However, all calendar dates in <see cref="XDate" /> and
|
|
/// <see cref="DateTime" />
|
|
/// are projected Gregorian calendar dates. Since the Gregorian calendar was not implemented
|
|
/// until October 4, 1582 (or later in some countries), Gregorian dates prior to that time are
|
|
/// really dates that would have been, had the Gregorian calendar existed. In order to avoid
|
|
/// throwing an exception, for dates prior to 1 AD, the year will be converted to a positive
|
|
/// year and the text "(BC)" is appended to the end of the formatted string. Under this mode, the
|
|
/// year sequence is 2BC, 1BC, 1AD, 2AD, etc. There is no year zero.
|
|
/// </remarks>
|
|
/// <param name="xlDate">
|
|
/// The XL date value to be formatted in floating point double format.
|
|
/// </param>
|
|
/// <param name="fmtStr">
|
|
/// The formatting string to be used for the date. See
|
|
/// <see cref="System.Globalization.DateTimeFormatInfo" />
|
|
/// for a list of the format types available.</param>
|
|
/// <returns>A string representation of the date</returns>
|
|
public static string ToString( double xlDate, string fmtStr )
|
|
{
|
|
int year, month, day, hour, minute, second, millisecond;
|
|
|
|
if ( !CheckValidDate( xlDate ) )
|
|
return "Date Error";
|
|
|
|
XLDateToCalendarDate( xlDate, out year, out month, out day, out hour, out minute,
|
|
out second, out millisecond );
|
|
if ( year <= 0 )
|
|
{
|
|
year = 1 - year;
|
|
fmtStr = fmtStr + " (BC)";
|
|
}
|
|
|
|
if ( fmtStr.IndexOf("[d]") >= 0 )
|
|
{
|
|
fmtStr = fmtStr.Replace( "[d]", ((int) xlDate).ToString() );
|
|
xlDate -= (int) xlDate;
|
|
}
|
|
if ( fmtStr.IndexOf("[h]") >= 0 || fmtStr.IndexOf("[hh]") >= 0 )
|
|
{
|
|
fmtStr = fmtStr.Replace( "[h]", ((int) (xlDate * 24)).ToString("d") );
|
|
fmtStr = fmtStr.Replace( "[hh]", ((int) (xlDate * 24)).ToString("d2") );
|
|
xlDate = ( xlDate * 24 - (int) (xlDate * 24) ) / 24.0;
|
|
}
|
|
if ( fmtStr.IndexOf("[m]") >= 0 || fmtStr.IndexOf("[mm]") >= 0 )
|
|
{
|
|
fmtStr = fmtStr.Replace( "[m]", ((int) (xlDate * 1440)).ToString("d") );
|
|
fmtStr = fmtStr.Replace( "[mm]", ((int) (xlDate * 1440)).ToString("d2") );
|
|
xlDate = ( xlDate * 1440 - (int) (xlDate * 1440) ) / 1440.0;
|
|
}
|
|
if ( fmtStr.IndexOf("[s]") >= 0 || fmtStr.IndexOf("[ss]") >= 0 )
|
|
{
|
|
fmtStr = fmtStr.Replace( "[s]", ((int) (xlDate * 86400)).ToString("d") );
|
|
fmtStr = fmtStr.Replace( "[ss]", ((int) (xlDate * 86400)).ToString("d2") );
|
|
xlDate = ( xlDate * 86400 - (int) (xlDate * 86400) ) / 86400.0;
|
|
}
|
|
if ( fmtStr.IndexOf("[f]") >= 0 )
|
|
fmtStr = fmtStr.Replace( "[f]", ((int) (xlDate * 864000)).ToString("d") );
|
|
if ( fmtStr.IndexOf("[ff]") >= 0 )
|
|
fmtStr = fmtStr.Replace( "[ff]", ((int) (xlDate * 8640000)).ToString("d") );
|
|
if ( fmtStr.IndexOf("[fff]") >= 0 )
|
|
fmtStr = fmtStr.Replace( "[fff]", ((int) (xlDate * 86400000)).ToString("d") );
|
|
if ( fmtStr.IndexOf("[ffff]") >= 0 )
|
|
fmtStr = fmtStr.Replace( "[ffff]", ((int) (xlDate * 864000000)).ToString("d") );
|
|
if ( fmtStr.IndexOf("[fffff]") >= 0 )
|
|
fmtStr = fmtStr.Replace( "[fffff]", ((int) (xlDate * 8640000000)).ToString("d") );
|
|
|
|
//DateTime dt = XLDateToDateTime( xlDate );
|
|
if ( year > 9999 )
|
|
year = 9999;
|
|
DateTime dt = new DateTime( year, month, day, hour, minute, second, millisecond );
|
|
return dt.ToString( fmtStr );
|
|
}
|
|
|
|
/*
|
|
/// <summary>
|
|
/// Format this XDate value using the specified format string
|
|
/// </summary>
|
|
/// <param name="fmtStr">
|
|
/// The formatting string to be used for the date. The following formatting elements
|
|
/// will be replaced with the corresponding date values:
|
|
/// <list type="table">
|
|
/// <listheader>
|
|
/// <term>Variable</term>
|
|
/// <description>Description</description>
|
|
/// </listheader>
|
|
/// <item><term>&mmmm</term><description>month name (e.g., January)</description></item>
|
|
/// <item><term>&mmm</term><description>month abbreviation (e.g., Apr)</description></item>
|
|
/// <item><term>&mm</term><description>padded month number (e.g. 04)</description></item>
|
|
/// <item><term>&m</term><description>non-padded month number (e.g., 4)</description></item>
|
|
/// <item><term>&dd</term><description>padded day number (e.g., 09)</description></item>
|
|
/// <item><term>&d</term><description>non-padded day number (e.g., 9)</description></item>
|
|
/// <item><term>&yyyy</term><description>4 digit year number (e.g., 1995)</description></item>
|
|
/// <item><term>&yy</term><description>two digit year number (e.g., 95)</description></item>
|
|
/// <item><term>&hh</term><description>padded 24 hour time value (e.g., 08)</description></item>
|
|
/// <item><term>&h</term><description>non-padded 12 hour time value (e.g., 8)</description></item>
|
|
/// <item><term>&nn</term><description>padded minute value (e.g, 05)</description></item>
|
|
/// <item><term>&n</term><description>non-padded minute value (e.g., 5)</description></item>
|
|
/// <item><term>&ss</term><description>padded second value (e.g., 03)</description></item>
|
|
/// <item><term>&s</term><description>non-padded second value (e.g., 3)</description></item>
|
|
/// <item><term>&a</term><description>"am" or "pm"</description></item>
|
|
/// <item><term>&wwww</term><description>day of week (e.g., Wednesday)</description></item>
|
|
/// <item><term>&www</term><description>day of week abbreviation (e.g., Wed)</description></item>
|
|
/// </list>
|
|
/// </param>
|
|
/// <example>
|
|
/// <para>"&wwww, &mmmm &dd, &yyyy &h:&nn &a" ==> "Sunday, February 12, 1956 4:23 pm"</para>
|
|
/// <para>"&dd-&mmm-&yy" ==> 12-Feb-56</para>
|
|
/// </example>
|
|
/// <returns>A string representation of the date</returns>
|
|
public string ToString( string fmtStr )
|
|
{
|
|
return ToString( this.xlDate, fmtStr );
|
|
}
|
|
|
|
/// <summary>
|
|
/// Format the specified XL Date value using the specified format string
|
|
/// </summary>
|
|
/// <param name="xlDate">
|
|
/// The XL date value to be formatted in floating point double format.
|
|
/// </param>
|
|
/// <param name="fmtStr">
|
|
/// The formatting string to be used for the date. The following formatting elements
|
|
/// will be replaced with the corresponding date values:
|
|
/// <list type="table">
|
|
/// <listheader>
|
|
/// <term>Variable</term>
|
|
/// <description>Description</description>
|
|
/// </listheader>
|
|
/// <item><term>&mmmm</term><description>month name (e.g., January)</description></item>
|
|
/// <item><term>&mmm</term><description>month abbreviation (e.g., Apr)</description></item>
|
|
/// <item><term>&mm</term><description>padded month number (e.g. 04)</description></item>
|
|
/// <item><term>&m</term><description>non-padded month number (e.g., 4)</description></item>
|
|
/// <item><term>&dd</term><description>padded day number (e.g., 09)</description></item>
|
|
/// <item><term>&d</term><description>non-padded day number (e.g., 9)</description></item>
|
|
/// <item><term>&yyyy</term><description>4 digit year number (e.g., 1995)</description></item>
|
|
/// <item><term>&yy</term><description>two digit year number (e.g., 95)</description></item>
|
|
/// <item><term>&hh</term><description>padded 24 hour time value (e.g., 08)</description></item>
|
|
/// <item><term>&h</term><description>non-padded 12 hour time value (e.g., 8)</description></item>
|
|
/// <item><term>&nn</term><description>padded minute value (e.g, 05)</description></item>
|
|
/// <item><term>&n</term><description>non-padded minute value (e.g., 5)</description></item>
|
|
/// <item><term>&ss</term><description>padded second value (e.g., 03)</description></item>
|
|
/// <item><term>&s</term><description>non-padded second value (e.g., 3)</description></item>
|
|
/// <item><term>&a</term><description>"am" or "pm"</description></item>
|
|
/// <item><term>&wwww</term><description>day of week (e.g., Wednesday)</description></item>
|
|
/// <item><term>&www</term><description>day of week abbreviation (e.g., Wed)</description></item>
|
|
/// </list>
|
|
/// </param>
|
|
/// <example>
|
|
/// <para>"&wwww, &mmmm &dd, &yyyy &h:&nn &a" ==> "Sunday, February 12, 1956 4:23 pm"</para>
|
|
/// <para>"&dd-&mmm-&yy" ==> 12-Feb-56</para>
|
|
/// </example>
|
|
/// <returns>A string representation of the date</returns>
|
|
public static string ToString( double xlDate, string fmtStr )
|
|
{
|
|
string[] longMonth = { "January", "February", "March", "April", "May", "June",
|
|
"July", "August", "September", "October", "November", "December" };
|
|
string[] shortMonth = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
|
|
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
|
|
string[] longDoW = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday",
|
|
"Friday", "Saturday" };
|
|
string[] shortDoW = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
|
|
|
|
int year, month, day, hour, minute, second;
|
|
XLDateToCalendarDate( xlDate, out year, out month, out day, out hour, out minute, out second );
|
|
|
|
string resultStr = fmtStr.Replace( "&mmmm", longMonth[ month - 1 ] );
|
|
resultStr = resultStr.Replace( "&mmm", shortMonth[ month - 1 ] );
|
|
resultStr = resultStr.Replace( "&mm", month.ToString( "d2" ) );
|
|
resultStr = resultStr.Replace( "&m", month.ToString( "d" ) );
|
|
resultStr = resultStr.Replace( "&yyyy", year.ToString( "d" ) );
|
|
resultStr = resultStr.Replace( "&yy", (year%100).ToString( "d2" ) );
|
|
resultStr = resultStr.Replace( "&dd", day.ToString( "d2" ) );
|
|
resultStr = resultStr.Replace( "&d", day.ToString( "d" ) );
|
|
resultStr = resultStr.Replace( "&hh", hour.ToString( "d2" ) );
|
|
resultStr = resultStr.Replace( "&h", (((hour+11)%12)+1).ToString( "d" ) );
|
|
resultStr = resultStr.Replace( "&nn", minute.ToString( "d2" ) );
|
|
resultStr = resultStr.Replace( "&n", minute.ToString( "d" ) );
|
|
resultStr = resultStr.Replace( "&ss", second.ToString( "d2" ) );
|
|
resultStr = resultStr.Replace( "&s", second.ToString( "d" ) );
|
|
resultStr = resultStr.Replace( "&a", (hour>=12) ? "pm" : "am" );
|
|
resultStr = resultStr.Replace( "&wwww", longDoW[ XLDateToDayOfWeek( xlDate ) ] );
|
|
resultStr = resultStr.Replace( "&www", shortDoW[ XLDateToDayOfWeek( xlDate ) ] );
|
|
|
|
|
|
return resultStr;
|
|
}
|
|
*/
|
|
|
|
#endregion
|
|
}
|
|
}
|