Bug in VBA DateValue() in VBA Excel? - excel

When I use the formula datevalue("01/01/1900") I get 1 and formatted as a date it shows as 01/01/1900
When I use VBA
.Range("A1").Value = DateValue("01/01/1900")
it shows up as "02/01/1900" in the cell
How is this possible?
If i use for example
.Range("A1").Value = DateValue("01/01/1901")
it works fine!
Head Melted!!!
Microsoft state that - "Using the default date system in Microsoft Excel for Windows, the date_text argument must represent a date between January 1, 1900 and December 31, 9999"

In short, Excel's DateTime epoch is not the same as VBA's DateTime epoch. Although, they are the same once you get past February 28th, 1900.
From Joel Spolksy's blog:
In most modern programming environments, dates are stored as real
numbers. The integer part of the number is the number of days since
some agreed-upon date in the past, called the epoch. In Excel, today's
date, June 16, 2006, is stored as 38884, counting days where January
1st, 1900 is 1.
I started working through the various date and time functions in Basic
and the date and time functions in Excel, trying things out, when I
noticed something strange in the Visual Basic documentation: Basic
uses December 31, 1899 as the epoch instead of January 1, 1900, but
for some reason, today's date was the same in Excel as it was in
Basic.
Huh?
I went to find an Excel developer who was old enough to remember why.
Ed Fries seemed to know the answer.
"Oh," he told me. "Check out February 28th, 1900."
"It's 59," I said.
"Now try March 1st."
"It's 61!"
"What happened to 60?" Ed asked.
"February 29th. 1900 was a leap year! It's divisible by 4!"
"Good guess, but no cigar," Ed said, and left me wondering for a
while.
Oops. I did some research. Years that are divisible by 100 are not
leap years, unless they're also divisible by 400.
1900 wasn't a leap year.
"It's a bug in Excel!" I exclaimed.
"Well, not really," said Ed. "We had to do it that way because we need
to be able to import Lotus 123 worksheets."
"So, it's a bug in Lotus 123?"
"Yeah, but probably an intentional one. Lotus had to fit in 640K.
That's not a lot of memory. If you ignore 1900, you can figure out if
a given year is a leap year just by looking to see if the rightmost
two bits are zero. That's really fast and easy. The Lotus guys
probably figured it didn't matter to be wrong for those two months way
in the past. It looks like the Basic guys wanted to be anal about
those two months, so they moved the epoch one day back."
"Aargh!" I said, and went off to study why there was a checkbox in the
options dialog called 1904 Date System.
The information below was taken from this Super User answer.
As described in Microsoft KB 214058:
Days of the week before March 1, 1900 are incorrect in Excel
MORE INFORMATION
When the date system in Microsoft Excel was originally created, it was designed to be fully compatible with date systems used by other spreadsheet programs.
However, in this date system, the year 1900 is incorrectly interpreted as a leap year. Because there is no February 29 ("leap day") in the year 1900, the day of the week for any date before March 1, 1900 (the day after the "leap day"), is not computed correctly.
The "other spreadsheet programs" refer to Lotus 1-2-3, which was quite popular back then, and incorrectly assumed that year 1900 was a leap year. This is explained in even more detail in KB 214326:
Excel 2000 incorrectly assumes that the year 1900 is a leap year
MORE INFORMATION
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 assumption 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.
If this behavior were to be corrected, many problems would arise, including the following:
Almost all dates in current Microsoft Excel worksheets and other documents would be decreased by one day. Correcting this shift would take considerable time and effort, especially in formulas that use dates.
Some functions, such as the WEEKDAY function, would return different values; this might cause formulas in worksheets to work incorrectly.
Correcting this behavior would break serial date compatibility between Microsoft Excel and other programs that use dates.
If the behavior remains uncorrected, only one problem occurs:
The WEEKDAY function returns incorrect values for dates before March 1, 1900. Because most users do not use dates before March 1, 1900, this problem is rare.

Related

Compare two week numbers from different years in Excel

I have some calculations that are strongly dependent on "this week", "next week", etc.
Let's say I have a date (Column A). I can use WEEKNUM((A1), 2) in Column B to get the week number.
In Column C, I can enter this formula to check if the event is this week or next week.
=IF(B1=WEEKNUM((TODAY()),2),"this week",IF(B1=WEEKNUM((TODAY()+7),2),"next week","way in the future"))
This all works great until I have events that cross into next year. So December 31, 2019, will be week 53 and December 31, 2020, will be week 53.
This is an issue because I need a way to account that December 31, 2020 happens later than December 31, 2019.
How do I account for change in years in this formula?
Update:
Adding YEAR as an additional condition will allow me to compare if the date HAS a different year but it still won't let me dynamically calculate, this week, next week.
In this second example, I set two dates and set my computer time as December 31 2019. The result is that instead of reporting 1/1/2020 as "next week" the formula returns "way in the future" which is incorrect.
Is there basically a way to subtract or add weeks using serial week number since epoch time?
Eh, I think I figured it out. Instead of comparing week numbers, we extract the Monday of each week and perform a similar comparison like before. Except we now have the entire date instead of just the week number.
=IF(A2-MOD(A2-2,7)=TODAY()-MOD(TODAY()-2,7),"this week",IF(A2-MOD(A2-2,7)=TODAY()-MOD(TODAY()-2,7)+7,"next week","way in the future"))

How to calculate a... median? of hour/day/month of occurence?

My problem concerns day of month however, I can see that the same logic would apply to month number or hour number or any other variable that ends on some value and then starts from 0 again.
It is defined as follows: I'm trying to calculate a day of month when a payment is made to use it for a forecast. So I have for example for one case:
1 May 2016
2 June 2016
30 June 2016
29 July 2016
6 September 2016
A simple average would give me 14th, and the median would give me 6th. But the result I'm looking for is more like the 1st.
I see I could do it somehow by calculating geometric median, or euclidean distances after placing the points on a circle etc, but I believe it can be approached in a much simpler way. I also see that solving this problem with standard means and averages would cause a situation where it gives more than one result.
But if we add an assumption that it should occur once in 30 days/a month? Wouldn't this assumption make the problem easier?
Please let me know if you solved a similar problem before or if you have any ideas
If the result you are "looking for is more like the 1st", then I would hazard a guess that you are really looking at a series of monthly payments (perhaps falling due on the first of each month or the first working day of each month) and you want some measure of the deviation between the due date and the actual date of payment.
If that is the case then simply calculate the difference in days between the due date and the actual date of payment for each monthly payment (following a consistent convention such as positive values denote late payment and negative values are early) and then apply your chosen measure (median, mean, etc) to the series of differences.

Excel weeknum function returns wrong week

Question is as in title.
I have a cell, "D4", with the date "09/07/2016" in it. Adjacent cell has formula "=weeknum(D4,1)". The output of this function is "28". But on a Sunday-Saturday basis, Saturday the 9th of July wasn't in week 28 - it was in week 27.
I thought this might be something to do with Saturday/Sunday and when the week starts and finishes, etc, so I tried multiple different dates from last week - Monday the 4th, Tuesday the 5th, Wednesday the 6th, etc. In each case, "weeknum" returns a value of "28".
I only noticed the problem because I have a macro which uses the value of the cell with the week number to look for a spreadsheet saved by our accounts team on a weekly basis. As they have - correctly - saved the spreadsheet as "week 27", it didn't work. I initially assumed that the accounts team were wrong, but I checked online and they are correct.
How could this happen? Surely Excel can't be wrong and I must have made a mistake of some sort?
I know that there is an issue with Excel not following ISO standards for when weeks 53 and 1 begin and end, but I don't see how that could affect a mid-year week.
It did occur to me that the issue might be to do with UK versus US date formatting. But, of course, the 7th of June wasn't in week 28 either.
That all is documented in WEEKNUM.
There are two systems used for this function:
System 1 The week containing January 1 is the first week of the
year, and is numbered week 1.
System 2 The week containing the first Thursday of the year is the
first week of the year, and is numbered as week 1. This system is the
methodology specified in ISO 8601, which is commonly known as the
European week numbering system.
Syntax
WEEKNUM(serial_number,[return_type])
Return_type Week begins on System
...
21 Monday 2
So =WEEKNUM("09/07/2016",21) will calculate as defined in ISO 8601 since Return_type 21 is the only one with System 2.
ISOWEEKNUM
=ISOWEEKNUM("09/07/2016")
will also do it.
=ISOWEEKNUM(a2)-1 returns the correct week for me, the same as =WEEKNUM(a2,21)-1

Date is not converted exactly when read from excel

I have an Excel spreadsheet that is being read.
The value in the spreadsheet is 7/24/2014 10:43:33 AM
The cell value after being read using OpenXML is 41844.446908680555.
When I do this calculation to convert to a date:
dte = DateTime.FromOADate(double.Parse(value));
I get 7/24/2014 10:43:32 AM
Is this typical when converting date/time or am I missing something?
Thanks
It seems that DateTime.FromOADate(double.Parse(value)); is truncating rather than rounding the fractional seconds. Excel stores date/time as days and fractions of days since 1 Jan 1900 (with the intentional error of calling 1900 a leap year, supposedly for compatibility with Lotus 123 at the time).
Therefore, the number 41844.446908680555 translates to, given Excel's level of precision
7/24/2014 10:43:32.910
(actually: 7/24/2014 10:43:32.9099949030205)
Just format the cells as Dates. 41844.446908680555 is Excel's way of serializing the date value.
When Excel stores a date or time in stores it in a number format with the date January 1, 1900 = 1
so really when you’re storing a date with the date format you’re really just storing the numeric value of difference between the date and January 1, 1900
So for example 365 = jan-30-1900
And fractions of a number equal parts of the day so .5 = half a day or 12 hours.
And for the fun of it right now = 41885.75 or sept-3-2014 at 6PM or 41885.75 from jan 1 1900.
The reason why this is done is to now allowed dates to be used in mathematical functions. And it deals with a lot of problems that pop-up with dates such as leap year and also provides for easier ways to deal with time zones as well.

Is there a bug in Excel concerning dates?

Please don't ask how I stumbled upon this but please try the following:
Type "60" into a cell in Excel.
Set the data type to a date format
The date displayed (in my case at least) is February 29th, 1900.
However, February 29th, 1900 never occurred since 1900 was not a leap year (see Wikipedia).
Is this a bug or am I missing something?
No, it is not a bug in Excel and yes you are missing something.
Excel implemented the dates to match with Lotus 1-2-3 for which compatibility was required at the time so was designed to have this error. Lotus 1-2-3 had the bug of thinking 1900 was a leap year.
See Microsoft's documentation for the reasons why not to fix it.
Please. It is a bug. It was never documented in the original Excel for Windows specifications. The original Excel which was on the Mac years before it was on any Windows platform used a 1904-based date system. The original Excel authors did recognize the issue.
"Strictly speaking, that wasn't an issue with Excel 1.0, which ran only on Macs. The original version of the Mac (and Excel) supported dates starting in 1904, partly to avoid the issue with 1900 not being a leap year. It wasn't until Excel was ported to Windows (Excel 2.0) that the 1900 date system was introduced, so you can't blame any of us on the Excel 1.0 team for the decision (and so, of course, we wouldn't comment on it in the interview)."
https://www.geekwire.com/2015/recalc-or-die-30-years-later-microsoft-excel-1-0-vets-recount-a-project-that-defied-the-odds/
The bug was also on MS-BASIC and Multiplan.
It's not a bug - Excel accepts Feb 29th 1900 as a valid date. It's a historical issue.
Your 60 is being regarded as 'number of days since Jan 1 1900'.
More info:
http://polymathprogrammer.com/2009/10/26/the-leap-year-1900-bug-in-excel/

Resources