VB .NET DateAdd function has serious problems, I suggest you do not use it again.

Posted by NosaLee in .NET Programming on 30-08-2012. Tags: , , , , ,

Author: Nosa Lee
Original Address: http://www.seeksunslowly.com/vb-net-dateadd-function-serious-problems-suggest-not-use-again
To reprint this article, please indicate the source, thank you.
_____________________________________

Let’s take a look at DateAdd’s declaration first.

1
2
3
4
Public Function DateAdd(ByVal Interval As Microsoft.VisualBasic.DateInterval, _
ByVal Number As Double, ByVal DateValue As Date) As Date

Member of Microsoft.VisualBasic.DateAndTime

Note
DateAndTime is a module under Microsoft.VisualBasic Namespace, its declaration as below:
Public Module DateAndTime
Member of Microsoft.VisualBasic
So, we can use DateAdd function directly.

As You Know
1. In VB .NET, the Maximum value of Date data type is 12/31/9999 23:59:59, and the minimum value is 1/1/1 00:00:00.
2. You can get a new date (Date type, the return value) via adding some values (the second parameter) of a specific element of time (years, months, days, hours, minutes, seconds and so on, the first parameter) to a base time (the third parameter) by using DateAdd function.
3. the Number parameter is a Double data (the second parameter).
4. Once the result date is in Date data type scope, DateAdd function can work normally.

Today I Found a Problem
In the allowable range (1/1/1 00:00:00~12/31/9999 23:59:59), I added any value of years, months, days or hours to a base date by using DateAdd, it has not problem; but if I add some large value of minutes or seconds to a base time, the System.OverflowException exception was thrown (memory overflow). The message of this exception is:
Message=”Arithmetic operation resulted in an overflow.”

DateAdd Sample Code (Has Some Problems)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

'' The following code works normally.
MsgBox("Max Value of Date Data Type: " & Date.MaxValue)
MsgBox("Min Value of Date Data Type: " & Date.MinValue)
MsgBox("Add Years: " & DateAdd(DateInterval.Year, 9998, New Date(1, 1, 1)))
MsgBox("Add Months: " & DateAdd(DateInterval.Month, 9998 * 12, New Date(1, 1, 1)))
MsgBox("Add Days: " & DateAdd(DateInterval.Day, 9998 * 12 * 30, New Date(1, 1, 1)))
MsgBox("Add Hours: " & DateAdd(DateInterval.Hour, 9998 * 12 * 30 * 24, New Date(1, 1, 1)))
''

' The System.OverflowException exception will throw.
MsgBox("Add Minutes: " & DateAdd(DateInterval.Minute, 9998.0 * 12 * 30 * 24 * 60, New Date(1, 1, 1)))

' Works normally.
MsgBox("Add Minutes: " & DateAdd(DateInterval.Minute, 2147483647, New Date(1, 1, 1)))

'' The System.OverflowException exception will throw.
MsgBox("Add Minutes: " & DateAdd(DateInterval.Minute, 2147483648, New Date(1, 1, 1)))
MsgBox("Add Seconds: " & DateAdd(DateInterval.Second, 9998.0 * 12 * 30 * 24 * 60 * 60, New Date(1, 1, 1)))
''
End Sub

Simple Analysis
In the first problematic code line MsgBox(“Add Minutes: ” & DateAdd(DateInterval.Minute, 9998.0 * 12 * 30 * 24 * 60, New Date(1, 1, 1))), the value of the second parameter is 5,182,963,200, so I thought that it may exceed the scope of Integer data type.
After searched, the maximum value of Integer is 2,147,483,647, so I changed it to add 2,147,483,647, worked, and then I changed to 2,147,483,648, the System.OverflowException exception was thrown again.

Obviously, the data type of the second parameter is Integer actually, it is not Double data.
So, the problems of DateAdd function are:
1. Function declaration has error: the real data type of second parameter is Integer, NOT Double.
2. Design error: if you want to add minutes or seconds to a base date, even use the maximum value (2,147,483,647) for the second parameter, the result date still can not arrive the maximum value of Date data type.

Advanced Analysis
As you know, in fact, Microsoft.VisualBasic namespace is migrated from VB6 directly (it contains some common constants, modules and functions).
In VB6, the corresponding data type of VB .NET Integer is Long (have same scope).
After tested, in VB6, above problems also exist.
So, the above two problems already exist in VB6, and Microsoft had not fixed it during upgrading VB programming language.

It does not matter?
Maybe, you may feel that this issue does not matter: because even using 2,147,483,647 to indicate seconds, it already has 68 years time, it may be sufficient under normal circumstances.
But, you should know that the users may do the chaotic operation or test some odd dates deliberately in your program; moreover, 68 years are really not enough, even you cannot use it to calculate the birthday for most people…
So, we need to solve these problems.

Solution
Abandon using DateAdd function, and switch to System.DateTime structure.
System.DateTime not only can process seconds, but also the milliseconds is supportable.

System.DateTime Sample Code (Works Normally)

1
2
3
4
5
6
7
8
9
10
11
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

' Initialized dt to January 1 in the year 1.
Dim dt As System.DateTime = New System.DateTime(1, 1, 1)
' Try to add a large number that is greater than the maximum value of Integer data type. Worked!
MsgBox(dt.AddSeconds(2147483648))
' Add 9998 years (approximation) via a seconds number, worked!
MsgBox(dt.AddSeconds(9998.0 * 12 * 30 * 24 * 60 * 60))
' Add 998 years (approximation) via a milliseconds number, worked!
MsgBox(dt.AddMilliseconds(9998.0 * 12 * 30 * 24 * 60 * 60 * 1000))
End Sub

OK, as above, the simple and advanced analysis for DateAdd function’s problems and the final solution are overall given, I hope it is helpful for you.

Comments:

There are (1) Comments for the VB .NET DateAdd function has serious problems, I suggest you do not use it again.

Post a comment