//============================================================================ //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 { /// /// This struct encapsulates a date and time value, and handles associated /// calculations and conversions between various formats. /// /// /// 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. /// /// John Champion /// $Revision: 3.20 $ $Date: 2007/03/11 02:08:16 $ public struct XDate //: ICloneable { #region Fields & Constants // ========================================================================= // Internal Variables // ========================================================================= /// /// The actual date value in MS Excel format. This is the only data field in /// the struct. /// private double _xlDate; /// /// The Astronomical Julian Day number that corresponds to XL Date 0.0 /// public const double XLDay1 = 2415018.5; /// /// The minimum valid Julian Day, which corresponds to January 1st, 4713 B.C. /// public const double JulDayMin = 0.0; /// /// The maximum valid Julian Day, which corresponds to December 31st, 9999 A.D. /// public const double JulDayMax = 5373483.5; /// /// The minimum valid Excel Day, which corresponds to January 1st, 4713 B.C. /// public const double XLDayMin = JulDayMin - XLDay1; /// /// The maximum valid Excel Day, which corresponds to December 31st, 9999 A.D. /// public const double XLDayMax = JulDayMax - XLDay1; /// /// The number of months in a year /// public const double MonthsPerYear = 12.0; /// /// The number of hours in a day /// public const double HoursPerDay = 24.0; /// /// The number of minutes in an hour /// public const double MinutesPerHour = 60.0; /// /// The number of seconds in a minute /// public const double SecondsPerMinute = 60.0; /// /// The number of minutes in a day /// public const double MinutesPerDay = 1440.0; /// /// The number of seconds in a day /// public const double SecondsPerDay = 86400.0; /// /// The number of milliseconds in a second /// public const double MillisecondsPerSecond = 1000.0; /// /// The number of milliseconds in a day /// public const double MillisecondsPerDay = 86400000.0; /// /// The default format string to be used in when /// no format is provided /// // public const string DefaultFormatStr = "&d-&mmm-&yy &hh:&nn"; public const string DefaultFormatStr = "g"; #endregion #region Constructors // ========================================================================= // Constructors // ========================================================================= /// /// Construct a date class from an XL date value. /// /// /// An XL Date value in floating point double format /// public XDate( double xlDate ) { _xlDate = xlDate; } /// /// Construct a date class from a struct. /// /// /// A struct containing the initial date information. /// public XDate( DateTime dateTime ) { _xlDate = CalendarDateToXLDate( dateTime.Year, dateTime.Month, dateTime.Day, dateTime.Hour, dateTime.Minute, dateTime.Second, dateTime.Millisecond ); } /// /// Construct a date class from a calendar date (year, month, day). Assumes the time /// of day is 00:00 hrs /// /// An integer value for the year, e.g., 1995. /// 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. /// 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. public XDate( int year, int month, int day ) { _xlDate = CalendarDateToXLDate( year, month, day, 0, 0, 0 ); } /// /// Construct a date class from a calendar date and time (year, month, day, hour, minute, /// second). /// /// An integer value for the year, e.g., 1995. /// 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. /// 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. /// 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. /// 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. /// 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. public XDate( int year, int month, int day, int hour, int minute, int second ) { _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second ); } /// /// Construct a date class from a calendar date and time (year, month, day, hour, minute, /// second), where seconds is a value (allowing fractional seconds). /// /// An integer value for the year, e.g., 1995. /// 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. /// 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. /// 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. /// 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. /// 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. public XDate( int year, int month, int day, int hour, int minute, double second ) { _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second ); } /// /// Construct a date class from a calendar date and time (year, month, day, hour, minute, /// second, millisecond). /// /// An integer value for the year, e.g., 1995. /// 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. /// 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. /// 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. /// 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. /// 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. /// 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. 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 ); } /// /// The Copy Constructor /// /// The GraphPane object from which to copy public XDate( XDate rhs ) { _xlDate = rhs._xlDate; } /* /// /// Implement the interface in a typesafe manner by just /// calling the typed version of /// /// A deep copy of this object object ICloneable.Clone() { return this.Clone(); } /// /// Typesafe, deep-copy clone method. /// /// A new, independent copy of this class public XDate Clone() { return new XDate( this ); } */ #endregion #region Properties // ========================================================================= // Properties // ========================================================================= /// /// Gets or sets the date value for this item in MS Excel format. /// public double XLDate { get { return _xlDate; } set { _xlDate = value; } } /// /// Returns true if this struct is in the valid date range /// public bool IsValidDate { get { return _xlDate >= XLDayMin && _xlDate <= XLDayMax; } } /// /// Gets or sets the date value for this item in .Net DateTime format. /// public DateTime DateTime { get { return XLDateToDateTime( _xlDate ); } set { _xlDate = DateTimeToXLDate( value ); } } /// /// 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. /// public double JulianDay { get { return XLDateToJulianDay( _xlDate ); } set { _xlDate = JulianDayToXLDate( value ); } } /// /// Gets or sets the decimal year number (i.e., 1997.345) corresponding to this item. /// public double DecimalYear { get { return XLDateToDecimalYear( _xlDate ); } set { _xlDate = DecimalYearToXLDate( value ); } } #endregion #region Get/Set Date Methods /// /// Returns true if the specified date value is in the valid range /// /// The XL date value to be verified for validity /// true for a valid date, false otherwise private static bool CheckValidDate( double xlDate ) { return xlDate >= XLDayMin && xlDate <= XLDayMax; } /// /// Take the specified date, and bound it to the valid date range for the XDate struct. /// /// The date to be bounded /// An XLDate value that lies between the minimum and maximum valid date ranges /// (see and ) public static double MakeValidDate( double xlDate ) { if ( xlDate < XLDayMin ) xlDate = XLDayMin; if ( xlDate > XLDayMax ) xlDate = XLDayMax; return xlDate; } /// /// Get the calendar date (year, month, day) corresponding to this instance. /// /// An integer value for the year, e.g., 1995. /// An integer value for the day of the month, e.g., 23. /// An integer value for the month of the year, e.g., /// 8 for August. 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 ); } /// /// Set the calendar date (year, month, day) of this instance. /// /// An integer value for the year, e.g., 1995. /// An integer value for the day of the month, e.g., 23. /// An integer value for the month of the year, e.g., /// 8 for August. public void SetDate( int year, int month, int day ) { _xlDate = CalendarDateToXLDate( year, month, day, 0, 0, 0 ); } /// /// Get the calendar date (year, month, day, hour, minute, second) corresponding /// to this instance. /// /// An integer value for the year, e.g., 1995. /// An integer value for the day of the month, e.g., 23. /// An integer value for the month of the year, e.g., /// 8 for August. /// An integer value for the hour of the day, e.g. 15. /// An integer value for the minute, e.g. 45. /// An integer value for the second, e.g. 35. 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 ); } /// /// Set the calendar date (year, month, day, hour, minute, second) of this instance. /// /// An integer value for the year, e.g., 1995. /// An integer value for the day of the month, e.g., 23. /// An integer value for the month of the year, e.g., /// 8 for August. /// An integer value for the hour of the day, e.g. 15. /// An integer value for the minute, e.g. 45. /// An integer value for the second, e.g. 35. public void SetDate( int year, int month, int day, int hour, int minute, int second ) { _xlDate = CalendarDateToXLDate( year, month, day, hour, minute, second ); } /// /// Get the day of year value (241.345 means the 241st day of the year) /// corresponding to this instance. /// /// The day of the year in floating point double format. public double GetDayOfYear() { return XLDateToDayOfYear( _xlDate ); } #endregion #region Date Conversion Methods // ========================================================================= // Conversion Routines // ========================================================================= /// /// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second), /// first normalizing all input data values. /// /// /// 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 /// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The /// method will just append a "(BC)" notation to the end of any dates /// prior to 1 AD, since the struct throws an exception when formatting earlier dates. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The integer millisecond value (e.g., 374 for 374 milliseconds past the second). /// /// The corresponding XL date, expressed in double floating point format 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 ); } /// /// Calculate an XL Date from the specified Calendar date (year, month, day, hour, minute, second), /// first normalizing all input data values. /// /// /// 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 /// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The /// method will just append a "(BC)" notation to the end of any dates /// prior to 1 AD, since the struct throws an exception when formatting earlier dates. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// The corresponding XL date, expressed in double floating point format 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 ); } /// /// 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. /// /// /// 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 /// struct projects only Gregorian dates backwards and does not deal with Julian calendar dates at all. The /// method will just append a "(BC)" notation to the end of any dates /// prior to 1 AD, since the struct throws an exception when formatting earlier dates. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The double second value (e.g., 42.3 for 42.3 seconds past the minute). /// /// The corresponding XL date, expressed in double floating point format 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 ); } /// /// Calculate an Astronomical Julian Day number from the specified Calendar date /// (year, month, day, hour, minute, second), first normalizing all input data values /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// The corresponding Astronomical Julian Day number, expressed in double /// floating point format 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 ); } /// /// Calculate an Astronomical Julian Day number from the specified Calendar date /// (year, month, day, hour, minute, second), first normalizing all input data values /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The integer second value (e.g., 325 for 325 milliseconds past the minute). /// /// The corresponding Astronomical Julian Day number, expressed in double /// floating point format 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 ); } /// /// 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. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second). /// 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; } /// /// 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. ) /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second). /// /// The corresponding XL date, expressed in double floating point format 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 ) ); } /// /// 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. ) /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The double millisecond value (e.g., 325.3 for 325.3 milliseconds past the second). /// /// The corresponding Astronomical Julian Day number, expressed in double /// floating point format 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; } /// /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to /// the specified XL date /// /// /// The XL date value in floating point double format. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// 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 ); } /// /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to /// the specified XL date /// /// /// The XL date value in floating point double format. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The integer millisecond value (e.g., 325 for 325 milliseconds past the second). /// 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; } /// /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to /// the specified XL date /// /// /// The XL date value in floating point double format. /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The double second value (e.g., 42.3 for 42.3 seconds past the minute). /// 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 ); } /// /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to /// the Astronomical Julian Day number /// /// /// The Astronomical Julian Day number to be converted /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// 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 ); } /// /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to /// the Astronomical Julian Day number /// /// /// The Astronomical Julian Day number to be converted /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The double second value (e.g., 42.3 for 42.3 seconds past the minute). /// 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; } /// /// Calculate a Calendar date (year, month, day, hour, minute, second) corresponding to /// the Astronomical Julian Day number /// /// /// The Astronomical Julian Day number to be converted /// /// /// The integer year value (e.g., 1994). /// /// /// The integer month value (e.g., 7 for July). /// /// /// The integer day value (e.g., 19 for the 19th day of the month). /// /// /// The integer hour value (e.g., 14 for 2:00 pm). /// /// /// The integer minute value (e.g., 35 for 35 minutes past the hour). /// /// /// The integer second value (e.g., 42 for 42 seconds past the minute). /// /// /// The millisecond value (e.g., 342.5 for 342.5 milliseconds past /// the second). /// 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; } /// /// Calculate an Astronomical Julian Day number corresponding to the specified XL date /// /// /// The XL date value in floating point double format. /// /// The corresponding Astronomical Julian Day number, expressed in double /// floating point format public static double XLDateToJulianDay( double xlDate ) { return xlDate + XLDay1; } /// /// Calculate an XL Date corresponding to the specified Astronomical Julian Day number /// /// /// The Astronomical Julian Day number in floating point double format. /// /// The corresponding XL Date, expressed in double /// floating point format public static double JulianDayToXLDate( double jDay ) { return jDay - XLDay1; } /// /// Calculate a decimal year value (e.g., 1994.6523) corresponding to the specified XL date /// /// /// The XL date value in floating point double format. /// /// The corresponding decimal year value, expressed in double /// floating point format 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 ); } /// /// Calculate a decimal year value (e.g., 1994.6523) corresponding to the specified XL date /// /// /// The decimal year value in floating point double format. /// /// The corresponding XL Date, expressed in double /// floating point format 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 ); } /// /// Calculate a day-of-year value (e.g., 241.543 corresponds to the 241st day of the year) /// corresponding to the specified XL date /// /// /// The XL date value in floating point double format. /// /// The corresponding day-of-year (DoY) value, expressed in double /// floating point format 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; } /// /// Calculate a day-of-week value (e.g., Sun=0, Mon=1, Tue=2, etc.) /// corresponding to the specified XL date /// /// /// The XL date value in floating point double format. /// /// The corresponding day-of-week (DoW) value, expressed in integer format public static int XLDateToDayOfWeek( double xlDate ) { return (int) ( XLDateToJulianDay( xlDate ) + 1.5 ) % 7; } /// /// Convert an XL date format to a .Net DateTime struct /// /// /// The XL date value in floating point double format. /// /// The corresponding XL Date, expressed in double /// floating point format /// The corresponding date in the form of a .Net DateTime struct 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 ); } /// /// Convert a .Net DateTime struct to an XL Format date /// /// /// The date value in the form of a .Net DateTime struct /// /// The corresponding XL Date, expressed in double /// floating point format 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 // ========================================================================= /// /// Add the specified number of milliseconds (can be fractional) to the current XDate instance. /// /// /// The incremental number of milliseconds (negative or positive) in floating point double format. /// public void AddMilliseconds( double dMilliseconds ) { _xlDate += dMilliseconds / MillisecondsPerDay; } /// /// Add the specified number of seconds (can be fractional) to the current XDate instance. /// /// /// The incremental number of seconds (negative or positive) in floating point double format. /// public void AddSeconds( double dSeconds ) { _xlDate += dSeconds / SecondsPerDay; } /// /// Add the specified number of minutes (can be fractional) to the current XDate instance. /// /// /// The incremental number of minutes (negative or positive) in floating point double format. /// public void AddMinutes( double dMinutes ) { _xlDate += dMinutes / MinutesPerDay; } /// /// Add the specified number of hours (can be fractional) to the current XDate instance. /// /// /// The incremental number of hours (negative or positive) in floating point double format. /// public void AddHours( double dHours ) { _xlDate += dHours / HoursPerDay; } /// /// Add the specified number of days (can be fractional) to the current XDate instance. /// /// /// The incremental number of days (negative or positive) in floating point double format. /// public void AddDays( double dDays ) { _xlDate += dDays; } /// /// Add the specified number of Months (can be fractional) to the current XDate instance. /// /// /// The incremental number of months (negative or positive) in floating point double format. /// 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; } } /// /// Add the specified number of years (can be fractional) to the current XDate instance. /// /// /// The incremental number of years (negative or positive) in floating point double format. /// 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 // ========================================================================= /// /// '-' operator overload. When two XDates are subtracted, the number of days between dates /// is returned. /// /// The left-hand-side of the '-' operator (an XDate class) /// The right-hand-side of the '-' operator (an XDate class) /// The days between dates, expressed as a floating point double public static double operator -( XDate lhs, XDate rhs ) { return lhs.XLDate - rhs.XLDate; } /// /// '-' operator overload. When a double value is subtracted from an XDate, the result is a /// new XDate with the number of days subtracted. /// /// The left-hand-side of the '-' operator (an XDate class) /// The right-hand-side of the '-' operator (a double value) /// An XDate with the rhs number of days subtracted public static XDate operator -( XDate lhs, double rhs ) { lhs._xlDate -= rhs; return lhs; } /// /// '+' operator overload. When a double value is added to an XDate, the result is a /// new XDate with the number of days added. /// /// The left-hand-side of the '-' operator (an XDate class) /// The right-hand-side of the '+' operator (a double value) /// An XDate with the rhs number of days added public static XDate operator +( XDate lhs, double rhs ) { lhs._xlDate += rhs; return lhs; } /// /// '++' operator overload. Increment the date by one day. /// /// The XDate struct on which to operate /// An XDate one day later than the specified date public static XDate operator ++( XDate xDate ) { xDate._xlDate += 1.0; return xDate; } /// /// '--' operator overload. Decrement the date by one day. /// /// The XDate struct on which to operate /// An XDate one day prior to the specified date public static XDate operator --( XDate xDate ) { xDate._xlDate -= 1.0; return xDate; } /// /// Implicit conversion from XDate to double (an XL Date). /// /// The XDate struct on which to operate /// A double floating point value representing the XL Date public static implicit operator double( XDate xDate ) { return xDate._xlDate; } /// /// Implicit conversion from XDate to float (an XL Date). /// /// The XDate struct on which to operate /// A double floating point value representing the XL Date public static implicit operator float( XDate xDate ) { return (float) xDate._xlDate; } /// /// Implicit conversion from double (an XL Date) to XDate. /// /// The XDate struct on which to operate /// An XDate struct representing the specified xlDate value. public static implicit operator XDate( double xlDate ) { return new XDate( xlDate ); } /// /// Implicit conversion from XDate to . /// /// The XDate struct on which to operate /// A struct representing the specified xDate value. public static implicit operator DateTime( XDate xDate ) { return XLDateToDateTime( xDate ); } /// /// Implicit conversion from to . /// /// The struct on which to operate /// An struct representing the specified DateTime value. public static implicit operator XDate( DateTime dt ) { return new XDate( DateTimeToXLDate( dt ) ); } #endregion #region General Overrides // ========================================================================= // System Stuff // ========================================================================= /// /// Tests whether obj is either an structure or /// a double floating point value that is equal to the same date as this XDate /// struct instance. /// /// The object to compare for equality with this XDate instance. /// This object should be either a type XDate or type double. /// Returns true if obj is the same date as this /// instance; otherwise, false 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; } /// /// Returns the hash code for this structure. In this case, the /// hash code is simply the equivalent hash code for the floating point double date value. /// /// An integer representing the hash code for this XDate value public override int GetHashCode() { return _xlDate.GetHashCode(); } #endregion #region String Format Conversion Methods // ========================================================================= // String Formatting Routines // ========================================================================= /// /// Format this XDate value using the default format string (). /// /// /// The formatting is done using the /// method in order to provide full localization capability. The DateTime struct is limited to /// dates from 1 AD onward. However, all calendar dates in and /// 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. /// /// /// The XL date value to be formatted in floating point double format. /// /// A string representation of the date public string ToString( double xlDate ) { return ToString( xlDate, DefaultFormatStr ); } /// /// Format this XDate value using the default format string (see cref="DefaultFormatStr"/>). /// /// /// The formatting is done using the /// /// method in order to provide full localization capability. The DateTime struct is limited to /// dates from 1 AD onward. However, all calendar dates in and /// /// 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. /// /// A string representation of the date public override string ToString() { return ToString( _xlDate, DefaultFormatStr ); } /// /// Format this XL Date value using the specified format string. The format /// string is specified according to the class. /// /// /// The formatting is done using the /// /// method in order to provide full localization capability. The DateTime struct is limited to /// dates from 1 AD onward. However, all calendar dates in and /// /// 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. /// /// /// The formatting string to be used for the date. See /// /// class for a list of the format types available. /// A string representation of the date public string ToString( string fmtStr ) { return ToString( this.XLDate, fmtStr ); } /// /// Format the specified XL Date value using the specified format string. The format /// string is specified according to the class. /// /// /// The formatting is done using the /// /// method in order to provide full localization capability. The DateTime struct is limited to /// dates from 1 AD onward. However, all calendar dates in and /// /// 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. /// /// /// The XL date value to be formatted in floating point double format. /// /// /// The formatting string to be used for the date. See /// /// for a list of the format types available. /// A string representation of the date 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 ); } /* /// /// Format this XDate value using the specified format string /// /// /// The formatting string to be used for the date. The following formatting elements /// will be replaced with the corresponding date values: /// /// /// Variable /// Description /// /// &mmmmmonth name (e.g., January) /// &mmmmonth abbreviation (e.g., Apr) /// &mmpadded month number (e.g. 04) /// &mnon-padded month number (e.g., 4) /// &ddpadded day number (e.g., 09) /// &dnon-padded day number (e.g., 9) /// &yyyy4 digit year number (e.g., 1995) /// &yytwo digit year number (e.g., 95) /// &hhpadded 24 hour time value (e.g., 08) /// &hnon-padded 12 hour time value (e.g., 8) /// &nnpadded minute value (e.g, 05) /// &nnon-padded minute value (e.g., 5) /// &sspadded second value (e.g., 03) /// &snon-padded second value (e.g., 3) /// &a"am" or "pm" /// &wwwwday of week (e.g., Wednesday) /// &wwwday of week abbreviation (e.g., Wed) /// /// /// /// "&wwww, &mmmm &dd, &yyyy &h:&nn &a" ==> "Sunday, February 12, 1956 4:23 pm" /// "&dd-&mmm-&yy" ==> 12-Feb-56 /// /// A string representation of the date public string ToString( string fmtStr ) { return ToString( this.xlDate, fmtStr ); } /// /// Format the specified XL Date value using the specified format string /// /// /// The XL date value to be formatted in floating point double format. /// /// /// The formatting string to be used for the date. The following formatting elements /// will be replaced with the corresponding date values: /// /// /// Variable /// Description /// /// &mmmmmonth name (e.g., January) /// &mmmmonth abbreviation (e.g., Apr) /// &mmpadded month number (e.g. 04) /// &mnon-padded month number (e.g., 4) /// &ddpadded day number (e.g., 09) /// &dnon-padded day number (e.g., 9) /// &yyyy4 digit year number (e.g., 1995) /// &yytwo digit year number (e.g., 95) /// &hhpadded 24 hour time value (e.g., 08) /// &hnon-padded 12 hour time value (e.g., 8) /// &nnpadded minute value (e.g, 05) /// &nnon-padded minute value (e.g., 5) /// &sspadded second value (e.g., 03) /// &snon-padded second value (e.g., 3) /// &a"am" or "pm" /// &wwwwday of week (e.g., Wednesday) /// &wwwday of week abbreviation (e.g., Wed) /// /// /// /// "&wwww, &mmmm &dd, &yyyy &h:&nn &a" ==> "Sunday, February 12, 1956 4:23 pm" /// "&dd-&mmm-&yy" ==> 12-Feb-56 /// /// A string representation of the date 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 } }