Converting Double to DateTime?

34,213

Solution 1

EDIT: As noted in comments and other answers, DateTime.FromOADate is a much better approach. I'll remove this answer if it's ever unaccepted. (But, there are still platforms like .NET Core where FromOADate is not supported so it is still useful for people using these platforms.)

I suspect you want:

DateTime date = new DateTime(1900, 1, 1).AddDays(days - 2);

(See other answers for why you need to subtract 2.)

Solution 2

To go from an DateTime in the "Excel Format" to a C# Date Time you can use the DateTime.FromOADate function.

In your example above:

   DateTime myDate = DateTime.FromOADate(41172);

To write it out for display in the desired format, use:

   myDate.ToString("dd/MM/yyyy");

If you are wondering where the discrepancies in Excel's date handling come from, it's supposed to be on purpose:

When Lotus 1-2-3 was first released, the program assumed that the year 1900 was a leap year even though it actually was not a leap year. This made it easier for the program to handle leap years and caused no harm to almost all date calculations in Lotus 1-2-3.

When Microsoft Multiplan and Microsoft Excel were released, they also assumed that 1900 was a leap year. This allowed Microsoft Multiplan and Microsoft Excel to use the same serial date system used by Lotus 1-2-3 and provide greater compatibility with Lotus 1-2-3. Treating 1900 as a leap year also made it easier for users to move worksheets from one program to the other.

Although it is technically possible to correct this behavior so that current versions of Microsoft Excel do not assume that 1900 is a leap year, the disadvantages of doing so outweigh the advantages.

Source: http://www.ozgrid.com/Excel/ExcelDateandTimes.htm

Solution 3

In case you are looking for FromOADate in .Net Core it is not there.

I dissembled the implementation .Net Framework and created an extension method.

        public static DateTime FromOADate(this double date)
        {
            return new DateTime(DoubleDateToTicks(date), DateTimeKind.Unspecified);
        }

        internal static long DoubleDateToTicks(double value)
        {
            if (value >= 2958466.0 || value <= -657435.0)
                throw new ArgumentException("Not a valid value");
            long num1 = (long)(value * 86400000.0 + (value >= 0.0 ? 0.5 : -0.5));
            if (num1 < 0L)
                num1 -= num1 % 86400000L * 2L;
            long num2 = num1 + 59926435200000L;
            if (num2 < 0L || num2 >= 315537897600000L)
                throw new ArgumentException("Not a valid value");
            return num2 * 10000L;
        }

Still need to test it.

Solution 4

The date format used by Excel is old, but is still supported by the DateTime.FromOADate function, which you can use to convert this number. It is defined as

number of days before or after the base date, midnight, 30 December 1899

Share:
34,213
Paul
Author by

Paul

Updated on July 09, 2022

Comments

  • Paul
    Paul almost 2 years

    I have a .CSV file which I am reading into a C# program. In one of the columns, there is a date, but it is in the "general" format, so it shows up in the .CSV as a number. For example: 41172.

    How can I convert this number to a date with format dd/mm/yyyy in C#? 41172 is equivalent to 20/09/2012.

  • Richard
    Richard over 11 years
    msdn.microsoft.com/en-us/library/… - "number of days before or after the base date, midnight, 30 December 1899"
  • Henk Holterman
    Henk Holterman over 11 years
    And the rumor is: because 1900 was not a leap-year but somebody forgot.
  • Paul
    Paul over 11 years
    it seems to be consistent so i can just subtract 2. thanks very much.
  • dash
    dash over 11 years
    @HenkHolterman The story I've heard was to maintain compatibility with Lotus 1-2-3 which had this bug originally.
  • Henk Holterman
    Henk Holterman over 11 years
    @dash: and how did it get into Lotus?
  • Henk Holterman
    Henk Holterman over 11 years
    2000 is a leap-year. Just like 1600 and 2400. So you're only right about 1900.
  • dash
    dash over 11 years
    @HenkHolterman Classic Recursion bug; they thought they were maintaining compatibility with Microsoft ;-)
  • Tom Chantler
    Tom Chantler over 11 years
    @Henk: Thank you! I did know this, but somehow forgot. Lol, I am a moron! I will edit my answer...
  • Jon Skeet
    Jon Skeet over 11 years
    @Paul: If you unaccept this answer to accept another one (e.g. dash's) I'll delete this one.
  • CrazyPyro
    CrazyPyro almost 10 years
    Here's another fun anecdote about that same idiosyncrasy: joelonsoftware.com/items/2006/06/16.html