So How Does Visual Basic Help My Dating Success?

Here are some ways Visual Basic helps you get around the Year 2000 glitch.

The Date Data Type

Visual Basic has had a dedicated Date data type since version 4 and, prior to that (in versions 2 and 3) a Date Variant type with the same storage pattern. Dates can be declared and used like this:

Dim dteMyDate     As Date dteMyDate = DateSerial(1998, 2, 12) 

Or perhaps

dteMyDate = #2/12/98# 

The Date data type is actually stored as an IEEE double-precision floating point value, 8 bytes long. The data stored can represent dates from January 1 100 up to December 31 9999. Days are stored as whole numbers, with zero being December 30 1899. Dates prior to this are stored as negative values, those after are positive. In the example above, February 12 1998 is stored as 35838. You can test this outcome with the following code:

MsgBox CDbl(DateSerial(1998, 2, 12))  

The Date data type is also able to hold time information. Hours, minutes, and seconds are held as fractions, with noon represented as 0.5. If we take the number of seconds in a day, 86400, and divide that into 1, the answer is the fraction equal to one second: 0.000011574…. The table below shows the minimum, default, and maximum values that can be stored in a variable declared as a Date.

  Date Value Stored
Minimum Value January 1 100 00:00:00 -657434
Default Value December 30 1899 00:00:00 0
Maximum Value December 31 9999 23:59:59 2958465.99998843

As we can see, there is nothing wrong with the way Visual Basic stores dates. Its method is both compact and Year 2000 compliant. For example, 8 bytes would store only the date if encoded as an alphanumeric CCYYMMDD. In effect, the Date data type allows us to store the time for free.

Manipulating Dates in Visual Basic

Once all your dates are stored in Date variables, all the date manipulation functions become available. The benefits of these functions are obvious—they are Year 2000 compliant and leap year aware.

Visual Basic has a number of date manipulation functions. In this section we are going to look at them in some detail. It might seem like I am telling you something you already know, but I have seen too many supposedly good Visual Basic developers remain unaware of the range of tools that are in the box.

Date tools

Visual Basic provides a lot of properties and functions that support comparison and manipulation of dates. These properties and functions are all designed to work with the Visual Basic Date data type and should be used in preference to all other methods. The majority of these elements reside in the VBA library in a class called DateTime. You can see the details of the class in Figure 8-1.

Figure 8-1 The VBA.DateTime class as seen in the Visual Basic Object Browser

TIP


With all the conversion functions, you would do well to use IsDate to test your expression before you perform the conversion.

The Calendar property This property exposes the calendar system currently in use within your application. By default this is set to vbCalGreg, the Gregorian calendar in use throughout most of the western world. Currently the only alternative is vbCalHijri, the Hijri calendar.

The Now, Date, Date$, Time, and Time$ properties All these properties perform similar tasks. They retrieve or assign the system date or time. By far the most used is the read-only Now property, which returns the current system date and time as a Visual Basic Date that can be assigned directly to a Date data type variable without conversion.

The Date and Time properties can be used to assign or return just the date or time part of the current system date. When assigning, the Date property expects to be passed a date expression containing the date you want to set the system date to. Any time information is ignored. The date must be within the range shown in the table below. Dates outside this range will result in a run-time error (5 - Invalid Procedure Call Or Argument). The Date$ property returns and assigns dates from Strings, with the equivalent Date property using Variants.

Range for VBA.DateTime.Date Windows 9x Windows NT
Minimum Date January 1 1980 January 1 1980
Maximum Date December 31 2099 December 31 2099

The Time and Time$ properties perform a task similar to Date and Date$, exposing the system time.

The Timer property This property returns the number of seconds that have elapsed since midnight.

The DateDiff function This function performs a comparison of two dates. The value that is returned—the difference between the two dates—is reported in a time or date unit of the caller's choosing. An important point to note is that the answer will correctly reflect the fact that the year 2000 is a leap year. The following code displays the difference, in number of days (specified by the first argument), between the current system date and December 1, 2000.

' Display the number of days until Dec 1 2000. MsgBox DateDiff("d", Now, #12/1/2000# _                  , vbUseSystemDayOfWeek, vbUseSystem) 

The fourth and fifth arguments are both optional, allowing you to specify the first day of the week and the first week of the year. Both will default to the system values if omitted.

The DateAdd function This function is used to modify a Visual Basic Date, with the value returned being the new Date following modification. Again this routine is fully aware of the leap year rules. The following line of code adds one month to the date January 31 2000 and returns the result February 29 2000, correctly calculating that February will have 29 days in the year 2000.

' Add one month to Jan 31 2000. MsgBox DateAdd("m", 1, CDate("31 Jan 2000")) 

The Year, Month, and Day functions The Format$ function is often abused when a programmer needs to get only part of the information held in a date. I still come across newly written code where Format$ has been used to do this.

' Getting the month of the current date, the old way iMonth = CInt(Format$(Date, "MM")) ' And how to do it the new, more efficient way iMonth = Month(Date) 

Visual Basic provides the Year, Month, and Day functions to return these numeric values when passed a Date.

The Hour, Minute, and Second functions Not surprisingly, these functions perform a similar task to the Year, Month, and Day functions described above, except that they will return the numeric values representing the components of the time held in a Visual Basic Date.

The DatePart function This function returns the part of a passed date that you request in the unit of your choice. The above Year, Month, Day, Hour, Minute, and Second functions can perform the majority of the tasks that DatePart can, but the DatePart function does give you more flexibility, as demonstrated in the following code:

' Get the quarter of the current date. MsgBox DatePart("q", Now, vbUseSystemDayOfWeek, vbUseSystem) 

The third and fourth arguments are both optional, allowing you to specify the first day of the week and the first week of the year. Both will default to the system values if omitted.

The Weekday function This function will return the day of the week of the Date passed in as the first argument. The second optional argument allows you to specify the first day of the week.

' Get the current day of the week. MsgBox Weekday(Now, vbUseSystemDayOfWeek) 

The DateValue and TimeValue functions These two functions perform conversions from a String date expression to a Date data type; in this case the conversion will be of only the date for DateValue and the time for TimeValue. These functions are useful if you want to separate the two parts of a date for separate storage.

One point to note with these two functions is that you can get a Type Mismatch error if any part of the expression you are converting is not valid, even the part you are not interested in. Executing the code below will result in this error, even though the time part of the expression is valid.

' Try this; it causes a Type Mismatch error! MsgBox TimeValue("29 02 1900 12:15") 

The DateSerial and TimeSerial functions DateSerial and TimeSerial are less flexible than DateValue and TimeValue, requiring three numeric parameters to define the date or time you want to convert. The three parameters of the DateSerial function are the year, month, and day, in that order. TimeSerial expects hours, minutes, and seconds.

' Assign April 12 1998 to the date. dteMyDate = DateSerial(1998, 4, 12) ' Alternatively, assign the time 12:00:00. dteMyDate = TimeSerial(12, 00, 00) 

Both these functions have an interesting ability to accept values outside the normal range for each time period (excluding years). For instance, if you pass the year 1998 and the month 14 to the DateSerial function, it will actually return a date in the second month of 1999, having added the 14 months to 1998. The following line of code illustrates this. (Your output might look different depending on your system settings, but the date will be the same.)

Debug.Print "The Date is " & Format$( _              DateSerial (1998, 2, 29), "Long Date") The Date is 01 March 1998 

In this instance, DateSerial has correctly worked out that there is no February 29 in 1998, so it has rolled the month over to March for the extra day. We can use this ability to write a function that tells us whether any year is a leap year.

Public Function IsLeapYear(ByVal inYear As Integer) As Boolean     IsLeapYear = (29 = Day(DateSerial(inYear, 2, 29))) End Function 

Formatting and displaying dates

These functions can be found in the VBA.Strings module. All these functions are aware of the current system locale settings. Any strings returned will be in the language and style of this locale.

Locales have particular formats for such things as the date, time, and currency. For instance, a user on a PC in France would expect to read or be able to enter date information in a familiar format. Windows extends this formatting to cover common text such as the days of the week or the months of the year. Visual Basic is aware of the system locale and will use the information associated with it when interpreting and formatting dates.

The Format and Format$ functions The Format function and the Format$ function are interchangeable. These functions return a string containing the passed date in the specified format. By default there are seven predefined date formats, of which "Long Date" and "Short Date" are the most useful; these two formats coincide with the formats set in the Regional Settings dialog box, shown in Figure 8-2. You can access this dialog box from the Regional Settings option in the Control Panel. The user can use the Date property page of this dialog box to modify both the Short Date and Long Date formats. These formats are directly supported by the Format$ function.

Figure 8-2 The Windows Control Panel, Regional Settings Properties dialog box

If we convert a Date to a string without applying a format we will actually assign the date in General Date format. For the U.S. this defaults to M/d/yy; for the U.K. and much of Europe it defaults to dd/MM/yy. The code extract below will display the date in a message box using the system General Date format. (See the table on the following page for a description of the General Date format.) You can experiment by changing the Short Date and Long Date formats and rerunning the code.

Dim dteMyDate As Date dteMyDate = DateSerial(1997, 2, 12) MsgBox CStr(dteMyDate) 

To use any named format other than General Date, we have to explicitly specify the format with the Format$ function. We can substitute the following line for the MsgBox line in the code above:

MsgBox Format$(dteMyDate, "Long Date" _                , vbUseSystemDayOfWeek, vbUseSystem) 

The third and fourth arguments are both optional, allowing you to specify the first day of the week and the first week of the year. Both will default to the system values if omitted.

The format types are very useful for displaying dates, either on line or within reports. Here the user has some control over the format via the Control Panel, and you maintain consistency with many other applications.

CAUTION


The size of date and time formats can be changed. As this is outside your application's direct control, you should allow sufficient space for any eventuality. Even when using the default General Date format we cannot assume a fixed length string. Dates in the 20th century will be formatted with two-digit years; dates in any other century, however, will be formatted with four-digit years. This behavior is consistent, even when we move the system date into the 21st century.

Notice that the formats in the table below are purely for coercing a Date into a String; they have no effect on the date value stored. A Date displayed using the Short Date format will still hold century information (indeed, it will hold the time too); it will just be coy about it. The Short Date format is particularly open to abuse, sometimes by so-called Year 2000 experts convinced that the PC problem can be solved by changing the Short Date format to include the century.

Format Name Description
General Date

(Default)

This will use the system Short Date format.

If the date to be displayed contains time information, this will also be displayed in the Long Time format.

Dates outside 1930 to 2029 will be formatted with century information regardless of the settings for the Short Date format in the Regional Settings.

Long Date This will use the Regional Settings system Long Date format.
Medium Date This will use a format applicable to the current system locale.

This cannot be set in the Regional Settings of the Control Panel.

Short Date This will use the Regional Settings system Short Date format.
Long Time This will use the Regional Settings system Time format.
Medium Time This will format the time using a 12-hour format.
Short Time This will format the time using a 24-hour format.

In addition to the predefined formats, you can apply your own formats. The weakness in using nonstandard formats for display purposes is that they are not controllable by the Regional Settings in the Control Panel. So if you are considering foreign markets for your software, you might have to modify your code for any change in regional date format (the different U.K. and U.S. formats are an obvious example). My advice is to use only the default formats wherever possible.

NOTE


Format$, DateAdd, and DateDiff are a little inconsistent with the tokens they use to represent different time periods. Format$ uses "n" as the token for minutes and "m" or "M" for months. However, DateAdd and DateDiff expect minutes as "m," and months as "M." Because the Regional Settings dialog box also uses "M," my advice would be to always use the upper-case letter when specifying the month in any of these functions.

If you convert a Date directly to a String without using Format, the resulting String will follow the general date rules except that dates outside the range 1930-1999 will be formatted with four-digit years, regardless of the settings for Short Date.

The FormatDateTime function This function is new to Visual Basic in version 6. It works in a similar way to Format$. However, FormatDateTime uses an enumerated argument for the format instead of parsing a string. This makes it less flexible than Format$, but faster. If you are going to be using only the system date formats, you should use FormatDateTime instead of Format$, giving you cleaner code and a slight performance improvement.

' Print the current system date. dteMyDate = FormatDateTime(Now, vbLongDate) 

The MonthName function Another addition to Visual Basic version 6, MonthName returns a string containing the name of the month that was passed in as an argument of type long. This function replaces one of the tricks that Format$ had often been called upon to do in the past: getting the name of a month.

' Give me the full name of the current month, the old way. MsgBox Format$(Now, "MMMM") ' Now do it the new way. MsgBox MonthName(Month(Now), False) 

This function has a second, optional Boolean argument that when set to True will cause the function to return the abbreviated month name. The default for this argument is False.

The WeekdayName function WeekdayName is another addition to Visual Basic 6. It works in a similar way to MonthName except that it returns a string containing the name of the day of the week.

' Give me the name of the current day of the week, ' the old way. MsgBox Format$(Now, "dddd", vbUseSystemDayOfWeek) ' Give me the full name of the current day of the week ' for the current system locale, the new way. MsgBox WeekdayName(Weekday(Now, vbUseSystemDayOfWeek), _                     False, vbUseSystemDayOfWeek) 

Again, the remaining arguments are optional. The first, if set to True, will cause the function to return the abbreviation of the day of the week; the second tells the function what day to use as the first day of the week.

The conversion and information functions

The last set of functions we are going to look at are the conversion functions. The CDate and CVDate functions CDate and CVDate both convert a date expression (ambiguous or not) directly into a Date data type. The difference is that CVDate actually returns a Variant of type vbDate (7) and is retained for backward compatibility with earlier versions of the language. The following code demonstrates two different ways of using CDate to retrieve a Date.

Dim dteMyDate   As Date ' This assigns December 31 1999 to the date... dteMyDate = CDate("31 Dec 1999") ' ...and so does this. dteMyDate = CDate(36525) 

CDate and CVDate perform a similar function to the DateValue function in the DateTime library with two exceptions. First, they can convert numeric values to a Date. The example above shows CDate converting the numeric serial date value of 36525 to a date of December 31 1999. Second, they will include time information in the conversion if it is present.

These functions can be found in the VBA.Conversion module, along with the other conversion functions such as CLng and CInt.

The IsDate function This function performs a simple but vital task. If passed a date expression, it will return True if the expression can be converted to a Visual Basic Date successfully. This is of great use when validating dates from sources directly outside your control, such as the user (the bane of all developers' lives).

If True = IsDate(txtDateOfBirth.Text) Then         ' Convert the expression entered to a date.     dteDOB = CDate(txtDateOfBirth.Text) Else     ' Otherwise, inform the user of his or her mistake.     MsgBox "Don't be silly. That is not a valid date." End If 

To add a final bit of complexity to everything, this function lives in a fourth module, VBA.Information.



Ltd Mandelbrot Set International Advanced Microsoft Visual Basics 6. 0
Advanced Microsoft Visual Basic (Mps)
ISBN: 1572318937
EAN: 2147483647
Year: 1997
Pages: 168

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net