Date and Time

 

Dates

A date is a unit that measures the number of years, months, or days elapsed in a series of alternate sunrises and sunsets. To represent the dates, computers, applications, and compilers are configured with specific techniques. The C++ Builder compiler counts dates from 12/30/1899 at midnight. With this compiler, dates and related operations are dealt with using a class called TDateTime. Since this class is not a control, you can use it with any control that displays text.

The dates used in your applications will mostly be based on the TDateTime class. To perform most operations in your programs, you will need to know when, how, and where to use this class. As an object, you will need to declare it.

 

Declaring a Date

To declare a date value, use one of the TDateTime constructors:

__fastcall TDateTime();
__fastcall TDateTime(const TDateTime& src);
__fastcall TDateTime(const TDateTimeBase& src);
__fastcall TDateTime(const double src);
__fastcall TDateTime(const int src);
enum TDateTimeFlag {Date, Time, DateTime};
__fastcall TDateTime(const AnsiString& src,
		     TDateTimeFlag flag = DateTime);
__fastcall TDateTime(unsigned short year,
		     unsigned short month,
		     unsigned short day);
__fastcall TDateTime(unsigned short hour,
		     unsigned short min,
		     unsigned short sec,
		     unsigned short msec);

The simplest way is to use the default constructor and provide a valid C++ name. Here is an example:

TDateTime Mine;

If not assigned a value, this variable is initialized to 12/30/1899 at midnight. If you know the exact date that you want to initialize, you have two alternatives. You can initialize the variable using a string. Here is an example:

TDateTime Mine("12/05/1990");

This could also be written as:

AnsiString S = "05/04/1988";
TDateTime Mine = S;

You can also provide the integer values of the year, the month, and the day respectively. Here is an example:

TDateTime Mine(1990, 11, 26);

To initialize a date, you can also provide an integer that represents the number of days passed since 1899 to the specified date. Here is an example:

TDateTime Mine = 33895;

The Date() Function

The simplest way to get the date in your application consists of calling the Date() function. For example, you can use it to display the current date:

  • In an Edit control: edtToday->Text = Date();
  • On a label: Label1->Caption = Date();
  • In a form’s title bar: Form1->Caption = Date();

Date, String, and Numeric Conversions

 

Converting a String to Date

Unless you are using a special control that recognizes date values, most of the controls will receive and display text. For this reason, as far as the compiler is concerned, the user or the client of a control would be supplying text derived from an AnsiString class. Therefore, before performing any operation on such a text, you will have to convert the content of the control to a valid date. In the same way, if you want the compiler to consider a date value as a “normal” string, you would convert the date value into a string.

If the user types a valid date into an edit box, such as 10/4/1988, this is still considered a string and you would not be able to use it in an operation. To convert a string to a date, you can use the StrToDate() function. Its syntax is:

TDateTime __fastcall StrToDate(const AnsiString S);

This function takes an argument as the string that needs to be converted. The string must be provided in a recognizable format, following the Regional Settings of the Windows Control Panel. For example, in the United States, the components of a date are separated with a forward slash “/”. The typical formats of a date are:

If the string contains an invalid date, the conversion would fail and the program would throw an error. If the conversion is successful, the function would return a valid date. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm2::btnConvertClick(TObject *Sender)
{
    TDateTime Value = StrToDate(edtSource->Text);
    edtTarget->Text = Value;
}
//---------------------------------------------------------------------------

Converting a Date to a String

The TDateTime and the AnsiString classes are configured to work in harmony and allow great flexibility. This allows a TDateTime date value to be easily recognized by, and converted to, an AnsiString string. Unless you are performing detailed formatting, a date value can be transparently identified as a string. For this reason, you can display a date value as a string without any conversion. As an example, when the user clicks a button named Button1 on a form, the date value of the AfewMonthsAgo variable would display in an Edit control named Edit1:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime AFewMonthsAgo("04/28/1998");
    Edit1->Text = AFewMonthsAgo;
}
//---------------------------------------------------------------------------

An AnsiString string is able to recognize a TDateTime value because the AnsiString is overloaded in the TDateTime class. Its syntax is:

__fastcall operator AnsiString() const;

The operator AnsiString() function allows any valid TDateTime value to be automatically converted to a string when needed. You can also explicitly use the function if necessary. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
    TDateTime AFewMonthsAgo("04/28/1998");
    AnsiString Converted = AFewMonthsAgo.operator AnsiString();
    edtResult->Text = Converted;
}
//---------------------------------------------------------------------------

If you have a date value that needs to be converted to a string, you can use the DateToStr() function. Its syntax is:

AnsiString __fastcall DateToStr(System::TDateTime Date);

This function takes one argument, which is the date value that needs to be converted. If the argument is not a valid date, the conversion would fail and the program would throw an error (in simple but practical terms, the program would crash). If the conversion is successful, the function returns a string. 

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
    AnsiString Current = DateToStr(Date());
    edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

Alternatively, you can use the TDateTime::DateString() function to convert a valid date to a string. The syntax of the DateString() method is:

AnsiString __fastcall DateString() const;

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime Today  = Date();
    AnsiString Value = Today.DateString();
    Edit1->Text      = Value;
}
//---------------------------------------------------------------------------

Converting a Date to a Double-Precision Number

A TDateTime value can be configured to display as a decimal number. The syntax used is:

__fastcall operator double() const;

The double data type was overloaded in the TDateTime class to allow converting a TDateTime variable to a fractional equivalent. The number can be made of two parts. If the number is round, that is, without a decimal value, it represents the number of days elapsed since 12/30/1899. If the number has a decimal part, the decimal portion represents a fraction of the day over a 24-hour period.

The operator double() function can be used to get the number of days and the amount of time elapsed since 12/30/1899 at midnight and the time of the current date. In the following example, the difference between the current date and time and 12/30/1899 at midnight is displayed as a double-precision number in an Edit control of a form when the form comes up:

//---------------------------------------------------------------------------
void __fastcall TForm2::FormCreate(TObject *Sender)
{
    TDateTime RightNow  = Now();
    double Qty          = RightNow.operator double();
    Edit1->Text         = Qty;
}
//---------------------------------------------------------------------------

To convert a TDateTime value to double using the double overloaded operator, declare a double variable and assign the TDateTime variable to it by calling the operator double() function. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);
    TDateTime Diff  = End - Start;
    double d        = Diff.operator double();
    edtDifference->Text = d;
}
//---------------------------------------------------------------------------
 

Converting a Date Value to an Integer

Like the double data type, the int data type was overloaded in the TDateTime class to convert a TDateTime value to an integer. The syntax of the function is:

__fastcall operator int() const;

To get the equivalent number of days of a TDateTime value, declare an integer and assign it the desired TDateTime value by calling the operator int() function. If the operator is applied on a variable that holds a particular and valid date, the operator int() function would produce the number of days elapsed since 12/30/1899. In the following example, the number of days since 12/30/1899 to the current date is displayed in an Edit control when the user clicks the button:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnShowDaysClick(TObject *Sender)
{
    TDateTime Today = Date();
    int Days = Today.operator int();
    edtDifference->Text = Days;
}
//---------------------------------------------------------------------------

The Computer’s System of Displaying Dates

Your computer and your customer’s use a set of attributes to display date values. These are provided or configured in the Regional Settings. To access the Regional Settings, in Microsoft Windows XP, click Start ª Control Panel. From the Control Panel, click Date, Time, Language, and Regional Options:



From the Date, Time, Language, and Regional Options window, click either Change the Format of Numbers, Dates, and Times or Regional and Language Options. From the Regional or Language Options, click the Regional Options property page and click the Customize button:

The computer uses two main categories of date display. These categories are based on the language used by your computer. For example, most user computers that reside in the United States use a standard known as US English. This commands how the date displays in the continental US. Each category uses specific characters to represent its value. The m or M is used for a month, the d or D is used for a day, and the y or Y is used for the year.

The Short Date Format

The Short Date Format is a special string that all applications of your computer refer to in order to display a date using the numeric version of a date.

The months hold the values 1=January, 2=February, 3=March, 4=April, 5=May, 6=June, 7=July, 8=August, 9=September, 10=October, 11=November, and 12=December. Instead on numbers, a month is represented with the letter m; the computer has the responsibility of finding the right month.

The computer refers to the following characters and it depends on how these characters are retrieved:

Character Meaning Why use it?
m or M The month displays as a single digit if the numeric month is less than 10 Can be used to display May as 5 instead of 05
mm or MM The month displays a leading 0 if the numeric month is less than 10 Can be used to display May as 05 instead of 5
d or D The day displays as a single digit if the day of the month is less than 10 Can be used to display the 8th of the month as 8 and not 08
dd or DD The day displays a leading 0 if the day of the month is less than 10 Can be used to display 8th day of the month as 08 and not 8
y, yy, Y, or YY The year displays with two digits like 88 for 1988 Used when two digits suffice to display the year
yyy, YYY, yyyy, YYYY The year displays with 4 digits such as 1988 and not 88 Used to display all digits for a year

To display a date value, use the syntax:

ShortDateFormat = “Format”;

To create a format, assign an appropriate string to the ShortDateFormat variable. After creating such a format, you can display a date value in the desired control. Before displaying the date, the compiler would scan the event or function and find out what format to apply. Here are examples of displaying individual portions of a date value:

//---------------------------------------------------------------------------
void __fastcall TfrmDates::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);

    ShortDateFormat = "d";
    edtd->Text = DateValue;
    ShortDateFormat = "dd";
    edtdd->Text = DateValue;
    ShortDateFormat = "M";
    edtM->Text = DateValue;
    ShortDateFormat = "MM";
    edtMM->Text = DateValue;
    ShortDateFormat = "y";
    edty->Text = DateValue;
    ShortDateFormat = "yy";
    edtyy->Text = DateValue;
    ShortDateFormat = "yyy";
    edtyyy->Text = DateValue;
    ShortDateFormat = "yyyy";
    edtyyyy->Text = DateValue;
}
//---------------------------------------------------------------------------

Besides using any of these characters to display their corresponding portion of a date, you can also combine these characters to display a semi or complete date. To do this, you will need a symbol or character that separates the portions of a date. In the US English, the most common character used to separate the portions of a date is the forward slash “/”. Another character used is the dash “-“.

Using a combination of the above characters, the operating system proposes a list of possible formats for date display. To access this list, from the Regional Options property page of the Regional and Language Options dialog box, you can click the arrow of the Short Date Format combo box. The combinations are:

Here are examples of displaying the formats specified by the operating system:

//---------------------------------------------------------------------------
void __fastcall TfrmMain::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);

    ShortDateFormat = "M/d/yyyy";
    edtMdyyyy->Text = DateValue;
    ShortDateFormat = "M/d/yy";
    edtMdyy->Text = DateValue;
    ShortDateFormat = "MM/dd/yy";
    edtMMddyy->Text = DateValue;
    ShortDateFormat = "MM/dd/yyyy";
    edtMMddyyyy->Text = DateValue;
    ShortDateFormat = "yy/MM/dd";
    edtyyMMdd->Text = DateValue;
    ShortDateFormat = "yyyy-MM-dd";
    edtyyyyMMdd->Text = DateValue;
    ShortDateFormat = "dd-MMM-yy";
    edtddMMMyy->Text = DateValue;
}
//---------------------------------------------------------------------------

In the same way, you can create your own formats.

The Long Date Format

The operating system provides a more explicit system of displaying date values. This is called the Long Date Format and it uses a global variable called LongDateFormat. This variable is defined in the Regional Options of the Control Panel. When using the LongDateFormat, there are various types of combinations applied to the characters, depending on what you are trying to display.

To display the date using the Long Date Format formats, the computer uses the following combinations:

Format Description
d The single d is used to display the numeric day of a month. Each month starts at 1, then 2, and so on. The month of February can have 28 or 29 days depending on whether the year is a leap year. The other months have 30 or 31 days. If the day occurs before the 10th, the number would display without the leading 0
dd The double d as dd displays the numeric day of the month, from 1 tom 31 depending on the month and whether it is a leap year for February. If the month occurs before October, it would display with the leading 0
M The single M is used to display the numeric position of the month. January is 1, February is 2 and December is 12. If the month occurs before October, it would display without the leading 0
MM The double M as MM displays the numeric position of a month from 1 to 12. If the number is less than 10, it would display with the leading 0
MMM The triple M as MMM displays the name of the month using three letters. It uses a global variable called ShortMonthNames. This variable is defined by the operating system. By default, the names of the month are Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, and Dec
MMMM The quadruple M as MMMM displays the complete name of a month as defined as the operating system. The variable used is called LongMonthNames. The names of the months are January, February, March, April, May, June, July, August, September, October, November, and December
Y or YY The single y or double yy is used to display the numeric year with the last two digits
YYY or YYYY The triple y as yyy or the quadruple one as yyyy is used to display all four digits of a year
 

Using Dates

 

Displaying Dates

Any control that uses an AnsiString can display a date. From the declarations we have seen, if you create an initialized date, you can use the DateToStr() function to display it. If you use a date variable declared with the default construction, the control would display the first date the compiler can recognize:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime Mine; Edit1->Text = DateToStr(Mine);
}
//---------------------------------------------------------------------------

If the date is initialized with a valid date value, you can omit the conversion function:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime Mine("12/05/1990");
    Edit1->Text = Mine;
}
//---------------------------------------------------------------------------

If you supply the integer values of the variable, the compiler would take care of displaying the equivalent date:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime Mine(1990, 11, 26);
    Edit1->Text = Mine;
}
//---------------------------------------------------------------------------

In the same way, if you initialize the variable with a number of days as an integer, the compiler would calculate and display the corresponding date:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime Mine  = 33895;
    Edit1->Text     = Mine;
}
//---------------------------------------------------------------------------
 

Decoding a Date

A date variable declared from the TDateTime class is made of a year, a month, and a day values. Decoding a date consists of isolating or retrieving these components of a date value. To perform such an operation, the TDateTime class is equipped with the DecodeDate() method. Its syntax is:

void __fastcall DecodeDate(unsigned short* year,
			   unsigned short* month,
			   unsigned short* day) const;

Each component is retrieved using a pointer to an unsigned short. The presence of pointers allows you to pass “empty” variables whose value would be altered by the function and returned with new values.

In the following example, the current date is stored in a TDateTime variable. Then the year, month, and day of the variable are extracted before constructing a sentence to display on a label:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TDateTime Today = Date();
    unsigned short Year, Month, Day;

    Today.DecodeDate(&Year, &Month, &Day);
    Label1->Caption = "Today is the " + String(Day) +
                      " of month " + Month +
                      " of the year " + Year + ".";
}
//---------------------------------------------------------------------------

If you want to display a better English version of the sentence above, you can format the date components to your liking. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    TDateTime Today = Date();

    AnsiString Dayth, Monthth;
    unsigned short Year, Month, Day;
    Today.DecodeDate(&Year, &Month, &Day);

    if( Day == 1 )
        Dayth = "st";
    else if( Day == 2 )
        Dayth = "nd";
    else if( Day == 3 )
        Dayth = "rd";
    else
        Dayth = "th";

    if( Month == 1 )
        Monthth = "st";
    else if( Month == 2 )
        Monthth = "nd";
    else if( Month == 3 )
        Monthth = "rd";
    else
        Monthth = "th";

    Label1->Caption = "Today is the " + String(Day) + Dayth +
                      " of the " + Month + Monthth +
                      " month of the year " + Year + ".";
}
//---------------------------------------------------------------------------

The DecodeDate() function comes in two versions. Besides the TDateTime’s, the VCL provides another version whose syntax is:

void __fastcall DecodeDate(System::TDateTime Date,
			   Word &Year,
			   Word &Month,
			   Word &Day);

Since this version is class-independent, the first argument you must supply is a TDateTime value or variable. This time, the year, the month, and the day values are passed by reference, which also allows the function to return them altered.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDecodeClick(TObject *Sender)
{
    TDateTime Typed = StrToDate(edtDate->Text);
    Word Year, Month, Day;

    DecodeDate(Typed, Year, Month, Day);

    edtDay->Text   = Day;
    edtMonth->Text = Month;
    edtYear->Text  = Year;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

If you want to get or display the English name of the decoded month, you can write a conditional switch whose cases would represent the months by their integral position. You can also declare an AnsiString variable to hold the names of months and retrieve the necessary one when needed. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDecodeClick(TObject *Sender)
{
    TDateTime Typed = StrToDate(edtDate->Text);
    Word Year, Month, Day;

    AnsiString Months[] = { "",
                            "January",   "February", "March",    "April",
                            "May",       "June",     "July",     "August",
                            "September", "October",  "November", "December"
                          };
    DecodeDate(Typed, Year, Month, Day);

    edtDay->Text   = Day;
    edtMonth->Text = Months[Month];
    edtYear->Text  = Year;
}
//---------------------------------------------------------------------------
 

Encoding a Date

Encoding a date consists of supplying the necessary components of a TDateTime to the compiler to create a valid TDateTime value. The function used to perform this operation is:

TDateTime __fastcall EncodeDate(Word Year, Word Month, Word Day);

This function takes three positive integers (unsigned short) that represent:

  • the year: valid values range from 0 to 9999;
  • the month: valid values range from 1 to 12; January is 1, February is 2, etc;
  • the day: this could be 28, 29, 30, or 31 depending on the month and whether the year is a leap year, which controls the number of days for the month of February.

The following form is equipped with four Edit controls named edtDay, edtMonth, edtYear and edtDate. When the user clicks the Encode button named btnEncode, the OnClick event retrieves the values of the day, the month, and the year from their respective edit boxes. Then the compiler creates a date from those and displays it in the Date edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEncodeClick(TObject *Sender)
{
    Word Day, Month, Year;

    Day   = edtDay->Text.ToInt();
    Month = edtMonth->Text.ToInt();
    Year  = edtYear->Text.ToInt();

    TDateTime Value = EncodeDate(Year, Month, Day);
    edtDate->Text = Value;
}
//---------------------------------------------------------------------------
 

Finding the Leap Year

One of the arduous operations performed on date values is to find out whether the year value of a date is a leap year. Luckily, the IsLeapYear() function can perform it. The syntax of this function is:

bool __fastcall IsLeapYear(Word Year);

This function takes an unsigned short integer argument variable and examines it. If the argument, which must be a valid year number, is a leap year, the function returns true; otherwise, it would return false. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    if( IsLeapYear(Edit1->Text.ToInt()) )
        Edit2->Text = "Leap Year";
    else
        Edit2->Text = "Not";
}
//---------------------------------------------------------------------------

The following example starts by requesting a date value from the user using an InputBox() function. Then the date is decoded to retrieve the year value. The year is examined to find out whether it is a leap year, using the IsLeapYear() function. The function displays a message box to show its findings:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnLeapYearClick(TObject *Sender)
{
    unsigned short Year, Month, Day;

    AnsiString Value = InputBox("Date and Time", "Enter a date: ",
                                "01/01/1900");
    TDateTime Examiner = StrToDate(Value);

    Examiner.DecodeDate(&Year, &Month, &Day);
    AnsiString LeapYear = IsLeapYear(Year) ?
                          " is a leap year" :
                          " is not a leap year";
    ShowMessage("The date you typed was " + Value + "\n" +
                AnsiString(Year) + LeapYear);
}
//---------------------------------------------------------------------------
 

The Day of the Week

The VCL is equipped with a special function that can be used to retrieve the day of the week for a given date. The function used is the DayOfWeek() and its syntax is:

int __fastcall DayOfWeek(System::TDateTime Date);

To use this function, pass a TDateTime value or variable to the DayOfWeek() function. The TDateTime object passed as argument must hold a valid date value. After execution, the function returns an integer between 1 (included) and 7 (included) that represents the position of the day. Sunday is referred to as the first day of the week and has a value of 1; Monday is 2, etc.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
    TDateTime Value = StrToDate(edtDate->Text);
    int Day = DayOfWeek(Value);
    edtDay->Text = Day;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

Of course, sometimes you will want to get or display the English name of the day. To do this, you can write a switch conditional statement that would display a name accordingly. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
    TDateTime Value = StrToDate(edtDate->Text);
    int Day = DayOfWeek(Value);
    AnsiString DayName;

    switch(Day)
    {
    case 1:
        DayName = "Sunday";
        break;
    case 2:
        DayName = "Monday";
        break;
    case 3:
        DayName = "Tuesday";
        break;
    case 4:
        DayName = "Wednesday";
        break;
    case 5:
        DayName = "Thursday";
        break;
    case 6:
        DayName = "Friday";
        break;
    case 7:
        DayName = "Saturday";
    }
    edtDay->Text = DayName;
}
//---------------------------------------------------------------------------

An alternative would be to declare an array of AnsiString strings to hold the names of the week days, then retrieve the necessary one using its corresponding position. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
    TDateTime Value = StrToDate(edtDate->Text);
    int Day = DayOfWeek(Value);
    AnsiString DayName[] = { "",
                             "Sunday", "Monday", "Tuesday", "Wednesday",
                             "Thursday", "Friday", "Saturday"
                            };
    edtDay->Text = DayName[Day];
}
//---------------------------------------------------------------------------

The DayOfWeek() function comes in two versions. Besides the VCL’s, the TDateTime class also is equipped with this method. Its syntax is:

int __fastcall DayOfWeek() const;

This version does not take an argument. Instead, it is called by a TDateTime variable that needs it. This function returns an integer that represents the weekly position of the day if the execution is successful. The equivalent version of the above program would be:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnGetItClick(TObject *Sender)
{
    TDateTime Value = StrToDate(edtDate->Text);
    int Day = Value.DayOfWeek();
    edtDay->Text = Day;
}
//---------------------------------------------------------------------------
 

Increasing Months on a Date

The addition operator of the TDateTime class is used to add a number of days to a date value. If you want to add months to a date value, you can use the IncMonth() function. Its syntax is:

TDateTime __fastcall IncMonth(const TDateTime Source, int Months);

This function takes two arguments. The first is the date value or variable that serves as the source or reference to work on. This argument must hold a valid TDateTime date value; otherwise the execution would fail. The second argument, Months is an integer that represents the number of months to be added to the first argument. If the addition is successful, the IncMonth() function returns a new TDateTime value.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtMonthsExit(TObject *Sender)
{
    TDateTime StartDate = edtStartDate->Text;
    int Months = edtMonths->Text.ToInt();
    TDateTime NextPeriod = IncMonth(StartDate, Months);
    edtNextPeriod->Text = NextPeriod;
}
//---------------------------------------------------------------------------

The IncMonth() is used to both add and subtract months from a date. To subtract months, pass the Months argument with a negative value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtMonthsExit(TObject *Sender)
{
    TDateTime StartDate, NextPeriod;
    int Months;

    if(edtMonths->Text != "")
    {
        StartDate = edtStartDate->Text;
        Months = edtMonths->Text.ToInt();
        NextPeriod = IncMonth(StartDate, Months);
        edtNextPeriod->Text = NextPeriod;
    }
    else
        edtNextPeriod->Text = edtStartDate->Text;
}
//---------------------------------------------------------------------------
 

Replacing a Date

 
void __fastcall ReplaceDate(TDateTime &Target, const TDateTime Source);

The ReplaceDate() function allows replacing one date with another. On the function, the Target argument is the new date whose value needs to be replaced by that of the Source argument. Since the starting point of the TDateTime class is on 12/30/1899, if the Source argument occurs before that the date, the ReplaceDate() function takes care of reconciling the negative date. Here is an example of using the function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnReplaceClick(TObject *Sender)
{
    TDateTime Original = StrToDate(edtOriginal->Text);
    TDateTime Replacement;
    ReplaceDate(Replacement, Original);
    edtReplacement->Text = DateToStr(Replacement);
}
//---------------------------------------------------------------------------

Comparison Operations on Dates

The TDateTime class was configured with many arithmetic and comparison operators. These are used on date values allowing you to use TDateTime variables as if they were regular variables.

The Comparison for Equality

To find out whether two data values are the same, simply apply the Equality operator on their values. Once you have two TDateTime values or variables, the compiler is configured to perform this comparison.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if(Start == End)
        pnlComparison->Caption = "Both dates are the same";
    else
        pnlComparison->Caption = "Those are different dates!";
}
//---------------------------------------------------------------------------

This comparison is possible because the Equality operator “==” was overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator ==(const TDateTime& Target) const;

To compare two dates using the overloaded Equality operator, call the operator==() on the desired date and supply the argument date value that is being compared against the Target. The above could have been written:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start.operator ==(End) )
        pnlComparison->Caption = "Both dates are the same";
    else
        pnlComparison->Caption = "Those are different dates!";
}
//---------------------------------------------------------------------------
 

The Comparison for Inequality

To find out whether two date values are not the same, simply apply the inequality operator on their values. Once you have two TDateTime values or variables, the compiler is configured to perform this comparison.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start != End )
        pnlComparison->Caption = "Those are different dates!";
    else
        pnlComparison->Caption = "Both dates are the same";
}
//---------------------------------------------------------------------------

This comparison is possible because the inequality operator “!=” is overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator !=(const TDateTime& Target) const;

To compare two dates using the overloaded inequality operator, call the operator==() on the desired date and supply the argument date value that is being compared against the Target. The above could have been written:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start.operator !=(End) )
        pnlComparison->Caption = "Those are different dates!";
    else
        pnlComparison->Caption = "Both dates are the same";
}
//---------------------------------------------------------------------------
 

 The Comparison for Inferiority

To find out whether a date occurs prior to another date, apply the “less than” comparison operator. To do this, use the operator as if both date values were normal integral or floating-point values. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start < End )
        pnlComparison->Caption = DateToStr(Start) + " occurs prior to " +
                                 DateToStr(End);
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

Alternatively, you can use the overloaded “less than” operator to find out when one date is less than another. The syntax used is:

bool __fastcall operator <(const TDateTime& Target) const;

To perform the above “less than” comparison, you could implement the event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start.operator<(End) )
        pnlComparison->Caption = DateToStr(Start) + " occurs prior to " +
                                 DateToStr(End);
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------
 

The Comparison for Inferiority or Equality

Two TDateTime values can be compared to find out whether they are the same or if a source date occurs prior to a target date. To perform this comparison, apply the “less than or equal” operator as if the values were regular integer or floating-point numbers.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start <= End )
        pnlComparison->Caption = "Your film will be ready after 5 O'Clock";
    else
        pnlComparison->Caption = "Wrong date sequence";
}
//---------------------------------------------------------------------------

This comparison operator is useful because the “less than or equal to” operator “<=” was overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator <=(const TDateTime& Target) const;

Using the <= overloaded operator, The comparison in the above event could have been written as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End = StrToDate(edtEnd->Text);

    if( Start.operator <=(End) )
        pnlComparison->Caption = "Your film will be ready after 5 O'Clock";
    else
        pnlComparison->Caption = "Wrong date sequence";
}
//---------------------------------------------------------------------------
 

The Comparison for Superiority

To find out if a source date occurs after a target date, apply the “greater than” comparison operator. This operator is used the same way you would for a regular integer or a floating-point values. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);

    if( Start > End )
        pnlComparison->Caption = DateToStr(Start) + " occurs after " +
                                 DateToStr(End);
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

This “greater than” comparison between two date values is possible because its operator was overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator >(const TDateTime& Target) const;

Using the overloaded operator, the previous event could have been implemented as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);

    if( Start.operator >(End) )
        pnlComparison->Caption = DateToStr(Start) + " occurs after " +
                                 DateToStr(End);
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------
 

The Comparison for Superiority or Equality

Two TDateTime values can be compared to find out whether they are the same or if a source date occurs after a target date. To perform this comparison, apply the “greater than or equal” operator as if the values were regular integer or floating-points.

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);

    if( Start >= End )
        pnlComparison->Caption = "Testing for ""\"Greater Than Or Equal To""\"";
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

Using this comparison, you can validate an intermediary operation. Even after finding out whether the first date is greater than or equal to the second, you can further refine your comparison inside of the comparison. In the following example, a message box displays if the “greater than or equal to” comparison returns false:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);

    if( Start >= End )
    {
        pnlComparison->Caption = "Testing for ""\"Greater Than Or Equal To""\"";
        if( Start > End )
            ShowMessage(DateToStr(Start) + " occurs after " + DateToStr(End));
        else if( Start == End )
            ShowMessage("Both dates occur at the same time");
    }
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

This comparison operator is accessible because the “greater than or equal to” operator “<=” was overloaded in the TDateTime class. Its syntax is:

bool __fastcall operator >=(const TDateTime& Target) const;

To perform the comparison in the above event using the <= overloaded operator, call the operator>=() method on the source date value and include the compared date as the Target argument. The above event could be written as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::pnlComparisonClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);

    if( Start.operator >=(End) )
    {
        pnlComparison->Caption = "Testing for ""\"Greater Than Or Equal To""\"";
        if( Start > End )
            ShowMessage(DateToStr(Start) + " occurs after " + DateToStr(End));
        else if( Start == End )
            ShowMessage("Both dates occur at the same time");
    }
    else
        pnlComparison->Caption = "I can't make up my mind";
}
//---------------------------------------------------------------------------

Operations on Dates

The TDateTime and other VCL functions allow you to perform various types of operations on a date value. Almost all types of operations and all types of comparisons are possible. All arithmetic and all logic comparison operators were overloaded to permit as much flexibility as possible. Some of the operations are possible directly on date values. When not possible or difficult, the decoder and encoder functions can be used to let the compiler work behind the scenes.

Assigning One Date to Another

To assign one date to another, simply use the assignment operator “=” as if the variables were regular values. In the following example, the user enters a starting date in an Edit control and finds out the number of days a customer of a car rental wants to keep the car. The clerk enters this value in the # of Days edit box. When the clerk clicks somewhere else, that is, when the edit box loses focus, the content of the edit box is checked. If the number of days is 1 or less, which means the customer wants the car for only one day, the first date is assigned to a second TDateTime variable and displays in the End Date edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::edtNbrOfDaysExit(TObject *Sender)
{
    TDateTime Start, End;
    int NbrOfDays;

    Start = StrToDate(edtStartDate->Text);
    NbrOfDays = StrToInt(edtNbrOfDays->Text);

    if(NbrOfDays <= 1)
    {
        End = Start;
        edtEndDate->Text = End;
    }
    else
    {
        edtEndDate->Text = "";
        edtEndDate->SetFocus();
    }
}
//---------------------------------------------------------------------------

Alternatively, the TDateTime has the assignment operator overloaded to allow assigning a date variable to another. The syntaxes of the function are:

TDateTime& __fastcall operator =(const TDateTimeBase& rhs);
TDateTime& __fastcall operator =(const TDateTime& rhs);
TDateTime& __fastcall operator =(const double rhs);
TDateTime& __fastcall operator =(const int rhs);

To assign one date to another using the operator =() function, use a valid TDateTime value or declare a TDateTime variable and call the operator=() overloaded function by supplying the intended target TDateTime variable. The above event could be rewritten as;

//---------------------------------------------------------------------------
void __fastcall TForm1::edtNbrOfDaysExit(TObject *Sender)
{
    TDateTime Start, End;
    int NbrOfDays;

    Start     = StrToDate(edtStartDate->Text);
    NbrOfDays = StrToInt(edtNbrOfDays->Text);

    if(NbrOfDays <= 1)
    {
        End.operator =(Start);
        edtEndDate->Text = End;
    }
    else
    {
        edtEndDate->Text = "";
        edtEndDate->SetFocus();
    }
}
//---------------------------------------------------------------------------
 

Adding Values to a Date

To add a number of days to a TDateTime value, simply add an integer to the intended date value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAdditionClick(TObject *Sender)
{

    TDateTime Start    = StrToDate(edtStart->Text);
    TDateTime Addition = Start + 5;
    edtAddition->Text  = Addition;
}
//---------------------------------------------------------------------------

You can also get the number of days from the user by using another control on the application. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEstimateClick(TObject *Sender)
{
    TDateTime DepositDate = edtDepositDate->Text;
    int Days = edtDays->Text.ToInt();
    TDateTime PickupDate = DepositDate + Days;
    edtPickupDate->Text = PickupDate;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

The addition operation is possible on a date value because its operator is overloaded in the TDateTime class. The TDateTime class provides a mechanism of adding a number of days to a date value. The syntaxes of the overloaded operator are:

TDateTime __fastcall operator +(const TDateTimeBase& rhs) const;
TDateTime __fastcall operator +(const TDateTime& rhs) const;
TDateTime __fastcall operator +(const double rhs) const;
TDateTime __fastcall operator +(const int rhs) const;

When applied to a TDateTime value, the addition operator “+” adds a number of days to a date. If the number added exceeds the end of year, the class will calculate and encode a date that corresponds to the date of the subsequent year:

To add a number of months to a date value, decode the date to retrieve its year, month, and day values. Add the intended number of months to your date and re-encode the date. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnAdditionClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtDate->Text);
    int Months = StrToInt(edtValue->Text);
    unsigned short Year, Month, Day;

    Start.DecodeDate(&Year, &Month, &Day);
    TDateTime End(Year, Month+Months, Day);
    edtResult->Text = DateToStr(End);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

To add a number of years to a date value, decode it to extract the year, month, and day values. Add the integral number of years to the source year. Here is an example:

 
//---------------------------------------------------------------------------
void __fastcall TForm1::btnAdditionClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtDate->Text);
    int Years = StrToInt(edtValue->Text);
    unsigned short Year, Month, Day;

    Start.DecodeDate(&Year, &Month, &Day);
    TDateTime End(Year+Years, Month, Day);
    edtResult->Text = DateToStr(End);
}
//---------------------------------------------------------------------------
 

Assigning an Added Date

You can add a value to a date variable and assign the new value to the original date. This is the same as using the += operator. The syntaxes used for this operator are:

TDateTime& __fastcall operator +=(const TDateTimeBase& rhs);
TDateTime& __fastcall operator +=(const TDateTime& rhs);
TDateTime& __fastcall operator +=(const double rhs);
TDateTime& __fastcall operator +=(const int rhs);

To add a number of days to an existing date value, you can use the += operator as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
    TDateTime OneDay = StrToDate(edtDate->Text);

    OneDay += 5;
    edtResult->Text = DateToStr(OneDay);
}
//---------------------------------------------------------------------------
 

Subtracting Dates

To get the number of days between two dates, perform the subtraction operation on their values. To do this, you can declare a double precision number or an integer that would store the subtracted number from the later date to the earlier. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);
    int Diff = End - Start;

    edtDifference->Text = Diff;
}
//---------------------------------------------------------------------------

To get the difference of years between two dates, apply the subtraction operator on their values to get the integral number of days. Then divide this number by 365. This difference produces the number of years in ranges of 365 days. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);
    int Years = End - Start;
    edtYears->Text = (Years / 365);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

As an alternative, you can decode both dates and subtract their year values; this would produce the difference of years with regards to the years, not the real dates. For example, the difference between 12/31/2001 and 01/01/2002 would produce a year. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);
    unsigned short StartYear, StartMonth, StartDay, EndYear, EndMonth, EndDay;

    Start.DecodeDate(&StartYear, &StartMonth, &StartDay);
    End.DecodeDate(&EndYear, &EndMonth, &EndDay);
    int Years = EndYear - StartYear;

    edtYears->Text = Years;
}
//---------------------------------------------------------------------------

To get the difference of months between two dates, perform the subtraction operator on their values to get the number of days elapsed and divide the result by 30. This would produce a number of months. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);
    int Months = End - Start;
    edtYears->Text = Months / 30;
}
//---------------------------------------------------------------------------

The subtraction operation is possible on TDateTime values because the subtraction operator “-“ is overloaded in the TDateTime class as follows:

TDateTime __fastcall operator -(const TDateTimeBase& rhs) const;
TDateTime __fastcall operator -(const TDateTime& rhs) const;
TDateTime __fastcall operator -(const double rhs) const;
TDateTime __fastcall operator -(const int rhs) const;

The subtraction operator “-“ is overloaded in the TDateTime class to allow getting the difference of days, that is, the elapsed number of days between two dates. The subtraction is performed as Date2 – Date1. In this case, if Date2 occurs after Date1, the result would be a positive number; otherwise a negative value would indicate that Date2 occurs before Date1.

You can also use the operator int() overloaded function to get the difference of days between two dates. To do this, declare an integer that stores the subtracted number between two TDateTime dates. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDifferenceClick(TObject *Sender)
{
    TDateTime Start = StrToDate(edtStart->Text);
    TDateTime End   = StrToDate(edtEnd->Text);
    TDateTime Diff = End - Start;
    int Days = Diff.operator int();
    edtDifference->Text = Days;
}
//---------------------------------------------------------------------------
 

Assigning a Subtracted Date

The -= operator is used to subtract a number of days from a date and assign the new value to the date (whose value has been subtracted). This operation is performed using the overloaded -= operator that uses the following syntaxes:

TDateTime& __fastcall operator -=(const TDateTimeBase& rhs);
TDateTime& __fastcall operator -=(const TDateTime& rhs);
TDateTime& __fastcall operator -=(const double rhs);
TDateTime& __fastcall operator -=(const int rhs);

To subtract a number of days from a date, you can use the subtraction operator. To assign the subtracted value to the original date, use the -= operator. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDisplayClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    int IntValue        = StrToInt(edtSubtract->Text);
    DateValue          -= IntValue;
    edtResult->Text     = DateToStr(DateValue);
}
//---------------------------------------------------------------------------
 

Decrementing a Date

To decrement a date value, declare a TDateTime variable and apply the – operator on its value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    static TDateTime Start = StrToDate(edtStartDate->Text);
    edtStartDate->Text     = Start--;
}
//---------------------------------------------------------------------------

The TDateTime class allows subtracting one day from a TDateTime value. This is done using the overloaded decrement operator whose syntaxes are:

TDateTime& operator --();
TDateTime operator --(int);

To decrement a date value using the -- overloaded operator, you have two options. To use the pre-decrement operator, as if you were using “--Value”, call the operator--() function. This would apply the operator before recalling the variable. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    static TDateTime Start = StrToDate(edtStartDate->Text);
    edtStartDate->Text = Start.operator--();
}
//---------------------------------------------------------------------------

To use the post-increment operator, which is the same as “Value--“, in which case the statement is called before being incremented, use the operator--(int) method. The int argument is not specific but you must supply it. Therefore, type any integer number between the parentheses. Remember that the argument supplied is not the decrementing value; it is only a “witness” but it is necessary. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    static TDateTime Start = StrToDate(edtStartDate->Text);
    edtStartDate->Text = Start.operator--(2);
}
//---------------------------------------------------------------------------
 

Incrementing a Date

To increment a date value, declare a TDateTime variable and use the ++ operator on its value. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnIncrementClick(TObject *Sender)
{
    static TDateTime Original = StrToDate(edtDate->Text);
    edtIncremented->Text = Original++;
}
//---------------------------------------------------------------------------

The TDateTime class allows you to add one day to a TDateTime value. This is done using the overloaded increment operator with the following syntaxes:

TDateTime& operator++();
TDateTime operator++(int);

To apply the pre-increment operator, as if you were using “++Value”, call the operator++() function. This would apply the operator before recalling the variable. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnIncrementClick(TObject *Sender)
{
    static TDateTime Original = StrToDate(edtDate->Text);
    edtIncremented->Text = Original.operator++();
}
//---------------------------------------------------------------------------

To use the post-increment operator, which is the same as “Value++“, in which case the statement is called before being incremented, use the operator++(int). The int argument is not specific but you must supply it. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnIncrementClick(TObject *Sender)
{
    static TDateTime Original = StrToDate(edtDate->Text);
    edtIncremented->Text = Original.operator++(12);
}
//---------------------------------------------------------------------------

This was the opening dialog box: This was performed after the first click: 

Formatting and Controlling the Display of Dates

The TDateTime class and the VCL provide special functions that can be used to control how the date values display in your application. Calling one of these functions, a date can use almost any format you see fit or any that makes your application user-friendly.

To control how a date value displays, the TDateTime class uses the FormatString() method. Its syntax is:

AnsiString __fastcall FormatString(const AnsiString& format);

The TDateTime::FormatString() method takes a string argument that specifies what format to apply. After formatting the date value, the method returns an AnsiString string.

Alternatively, the VCL has its own function that performs the same operation. Its syntax is:

AnsiString __fastcall FormaTDateTime(const AnsiString Format,
				     System::TDateTime DateValue);

The FormaTDateTime() function takes two arguments. The Format argument is a string that specifies how the date should be formatted. Since this function is not part of the TDateTime class, it needs a valid TDateTime date value to work on; that is the role of the DateValue argument.

The Default Display

The default format used by both the TDateTime::FormatString() and the FormaTDateTime() functions conforms to the ShortDateFormat of the Windows Control Panel. For these functions, that format is represented by the “c” string. You can still use it explicitly. For the TDateTime::FormatString() method, an example would be:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime DateValue("10/22/2001");
    Edit1->Text = DateValue.FormatString("c");
}
//---------------------------------------------------------------------------

A similar example applied on the FormaTDateTime() function would be:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime DateValue("10/22/2001");
    Edit1->Text = FormaTDateTime("c", DateValue);
}
//---------------------------------------------------------------------------
 

Displaying the Numeric Day

The days of months are numbered from 1 to 31, depending on the month. The formatting functions represent each of these days with the “d” format. Here is an example used for the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatStringClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("d");
}
//---------------------------------------------------------------------------

This would produce:

The implementation of this format using the FormatDateTime() function is:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormaTDateTimeClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormaTDateTime->Text = FormaTDateTime("d", DateValue);
}
//---------------------------------------------------------------------------

When the day has a numeric value that is less than 10, the default “c” and the “d” formats display its value without the leading 0. To display the leading 0 as in 02 or 08, use the “dd” format. Here is an example implemented using the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("dd");
}
//---------------------------------------------------------------------------

Using the FormatDateTime() function, you could have written the same event as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = FormatDateTime("dd", DateValue);
}
//---------------------------------------------------------------------------
 

Displaying Weekday Names

The names of the week use two formats: 3 letters or full name. To display a name with 3 letters, use the “ddd” format. The names will be Sun, Mon, Tue, Wed, Thu, Fri, or Sat. Here is an example using the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("ddd");
}//---------------------------------------------------------------------------

The same event using the FormatDateTime() function would be written as:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = FormaTDateTime("ddd", DateValue);
}
//---------------------------------------------------------------------------

To display the weekday and the numeric day of the month, you can create a format that combines both strings. When creating this string, the format must be separated inside the string so the compiler would know which format to apply and where. To separate the formats, you can use (almost) any character but you should conform to those used in your regional settings. One of the most regularly used separators on dates is the comma but the simplest separator is an empty space. Here is an example (using the TDateTime::FormatString() method):

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("ddd dd");
}
//---------------------------------------------------------------------------

To display the complete name of a weekday, use the “dddd” format string. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("dddd");
}
//---------------------------------------------------------------------------

You can also display the weekday followed by the numeric day of the month. Here is an example that uses the FormatDateTime() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = FormaTDateTime("dddd dd", DateValue);
}
//---------------------------------------------------------------------------
 

Displaying Numeric Months

Months are displayed using two categories: a number or a name.

To display the numeric range of a month, use the “m” format. The months are numbered as follows: 1=January, 2=February, 3=March, 4=April, 5=May, 6=June, 7=July, 8=August, 9=September, 10=October, 11=November, and 12=December. Here is an example that displays the numeric month of a date, using the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("m");
}
//---------------------------------------------------------------------------

Following the rules we applied to display a combination of a weekday and a month’s numeric day, you can display a month and the month’s numeric value. This time, instead of an empty space, you should use a character that would indicate that the date is displaying a combination of month and day (or day and month). The best character to use is the one that conforms to the regional settings of your computer. In the United States’ English, this would be the forward slash “/”. Here is an example that uses the FormatDateTime() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = FormaTDateTime("m/dd", DateValue);
}
//---------------------------------------------------------------------------

In the same way you can combine a weekday short name followed by the combination of day/month (or month/day) as you see fit. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    edtFormatString->Text = FormaTDateTime("ddd m/dd", DateValue);
}
//---------------------------------------------------------------------------

This would produce:

When using the “m” format, if the number of the month is less than 10, the compiler would display it as 1, 2, 3, 4, 5, 6, 7, 8 or 9, without the leading 0. If you want to display the leading zero for a month between 1 and 9, as 01 or 07, use the “mm” format. Here is an example with the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("mm");
}
//---------------------------------------------------------------------------

You can also use this format when constructing a combined date:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("dddd, mm/dd");
}
//---------------------------------------------------------------------------
 

Displaying Months Names

You can display a month by its name using one of two formats: short or long name. The short names of months are: Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, and Dec. To display a month with one of these names, use the “mmm” format. The following example uses the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("mmm");
}
//---------------------------------------------------------------------------

This time, the name of the month would become more explicit in a combined format. To create such a combined date, apply the rules we have reviewed so far. The following TDateTime::FormatString() implementation displays a date as short weekday-day-short month name combination:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("ddd dd mmm");
}
//---------------------------------------------------------------------------

You can also use a comma and space to separate the name of the weekday from the other components. The following event uses the FormatDateTime() function:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = FormaTDateTime("dddd, dd mmm", DateValue);
}
//---------------------------------------------------------------------------

To display a complete name of a month, use the “mmmm” format. The name would display as one of the following: January, February, March, April, May, June, July, August, September, October, November, and December; confirming to the Regional Settings of your computer. Here is an example that uses the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    AnsiString Formatter  = "ddd, d mmmm";
    edtFormatString->Text = DateValue.FormatString(Formatter);
}
//---------------------------------------------------------------------------

Another implementation that uses the FormatDateTime() function can display the weekday-day-month combination with an empty space as the separator:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    AnsiString Formatter  = "dddd, dd mmmm";
    edtFormatString->Text = FormaTDateTime(Formatter, DateValue);
}
//---------------------------------------------------------------------------
 

Displaying the Year

A year value can be displayed using 2 or 4 digits. To display a year value as a number between 00 and 99, use the “y” or the “yy” formats as follows (this event uses the TDateTime::FormatString() method):

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("y");
}
//---------------------------------------------------------------------------

To make the displays we have used so far a little more explicit, you can include the year value in a combined date string, as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("ddd dd mmm yy");
}
//---------------------------------------------------------------------------

Therefore, you can apply any combination of the formats we have used so far to display a date, as illustrated in the following FormaTDateTime() function call:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    AnsiString Formatter  = "dddd dd mmmm yy";
    edtFormatString->Text = FormaTDateTime(Formatter, DateValue);
}
//---------------------------------------------------------------------------

A year value represented with two digits is hardly explicit, unless you have a good reason for using it. The alternative is to use all four digits to display a year. This format is created with the “yyy” or the “yyyy” strings. Here is an example with the TDateTime::FormatString() method:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    edtFormatString->Text = DateValue.FormatString("yyy");
}
//---------------------------------------------------------------------------

Since this format would be the only one with four digits in a combined string, it makes a date easier to read. Once again, you can apply the rules we have used so far, to create and display a combined date. The default format used by Microsoft Windows for the English language is as Sunday, January 27, 2002. You can use the TDateTime::FormatString() method to create such a format as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    AnsiString Formatter  = "dddd, mmmm dd, yyyy";
    edtFormatString->Text = DateValue.FormatString(Formatter);
}
//---------------------------------------------------------------------------

Using these rules, you can display a date as you wish. The following FormatDateTime() function displays a date differently than the event above:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnFormatClick(TObject *Sender)
{
    TDateTime DateValue   = StrToDate(edtDate->Text);
    AnsiString Formatter  = "dddd d mmmm yyyy";
    edtFormatString->Text = FormaTDateTime(Formatter, DateValue);
}
//---------------------------------------------------------------------------
 

Doing Time

The time is a unit that measures the number of sequences from a fixed starting point between two days to the equivalent fixed point between the following two days. The starting point called Midnight and is positioned at night. A day is made of 24 non-spatial divisions; each one of these divisions is called an hour. An hour is made of 60 fractions and each one these fractions is called a minute. A minute is divided in 60; each one of those parts is called a second.

As done with dates, most of the operations performed on time values are centered around the TDateTime class. This class is based on a double-precision number initialized at 0.00. The constant 0.00 corresponds to 12/30/1899 at midnight. A double-precision number is made of two sections: an integer part and a decimal side. The integral part is a natural number with no decimal value, such as 8, 1450, or 32. For the TDateTime class, the integral section represents the number of days that have elapsed since 12/30/1899.

On a double-precision number, such as 204.58, the decimal part starts with a period “.” and is made of all digits on the right side of the period. For the TDateTime class, the decimal part represents the number of seconds that have elapsed since midnight on the day considered.

By default, the compiler refers to the Regional Settings of your computer to display the time, separating it in hour, minute, second, and AM/PM. The default symbol to separate the hour and the minute, or the minute and the second is “:”. To separate the seconds and the AM/PM, the compiler leaves a one-character empty space between them.

Declaring Time Variables

The time portion of a TDateTime object can be declared and manipulated as a value. To declare time variables, you will use one of the constructors of the TDateTime class. If you declare a variable using the default constructor, as TDateTime TimeValue, the time will be initialized to midnight or 12:00:00 AM.

The time in regular value is a floating number that ranges from 0 included to 1 excluded. More precisely, the time is a value defined as follows:

0 >= Time >= 0.99999

The 0 constant represents midnight while the 0.99999 double-precision number represents 12:59:59 PM. In between, 0.50 represents 12:00:00 PM (noon time), 0.325 represents 7:48:00 AM, and 0.738 represents 5:42:43 PM.

To declare a time variable, use the TDateTime class and specify the name for the variable. Here is an example:

TDateTime Mine;

If not assigned a value, this variable is initialized at midnight or 12:00:00 AM. You can display its value in an Edit control as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue;
    Edit1->Text = TimeValue;
}
//---------------------------------------------------------------------------

You can initialize a time value with a double-precision number between 0.00000 and 0.99999. Here is an example:

TDateTime Value = 0.2185;

Such an initialization is the same as:

TDateTime Value(0.2185);

You can also get the value from an intermediary action or request it from the user. This allows you, if necessary, to convert any floating-point number to a time value, as follows:

You can also use an independent floating-point number to initialize a time variable. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTimeClick(TObject *Sender)
{
    double Number = edtNumber->Text.ToDouble();
    TDateTime TimeValue = Number;
    edtTime->Text = TimeValue;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnCloseClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

Still using the default constructor, if you know the time you want to initialize a variable with, you can provide it. To do that, declare an instance of the TDateTime constructor and type the time value between the double-quotes of the parentheses. If the time is known only for the hour(s) and the minute(s), you can initialize it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue("08:22");
    Label3->Caption = TimeValue;
}
//---------------------------------------------------------------------------

When using this formula, the hour value must be between 0 and 23. Any other value outside of this range will cause an error. The minute value must range from 0 to 59; otherwise, an error would be thrown. If the hour portion has a value between 0 and 11:59, the time is set in the morning with the AM in the AM/PM section. If the hour portion is between 12 and 23, the time is set in the afternoon. When displaying it, the compiler, by default, calculates and displays the 0 to 12 portion and then displays PM in the AM/PM section.

You can also initialize a time value using the Hour:Minute:Second formula as a string. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue("20:22:52");
    Label3->Caption = TimeValue;
}
//---------------------------------------------------------------------------

Once again, in the absence of an AM/PM section, the compiler would consider the hour portion to evaluate whether the time occurs in the morning or in the afternoon. The value of the seconds must be between 0 and 59; otherwise, an error will be thrown.

You can also initialize a time value by specifying the AM/PM portion as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue("10:22:52 AM");
    Label3->Caption = TimeValue;
}
//---------------------------------------------------------------------------

The AM and the PM can be in uppercase or lowercase. In otherwords the AM/PM portion can be represented as AM, Am, aM, am, PM, Pm, pM, or pm. Only the characters A and P (uppercase or lowercase) are accepted as the first character. Only the M or m characters are accepted as the second character. Any other combination or other character will cause an error.

If you know the values of the hour, the minute, the second, and the millisecond, you can use them to initialize a time variable. To do this, you must supply the arguments in order following the constructor:

__fastcall TDateTime(unsigned short Hour, unsigned short Minute,
                     unsigned short Second, unsigned short Millisecond);

The hour value must be between 0 and 23. The minutes must be between 0 and 59. The Second argument must have a value between 0 and 59. Whenever the seconds are not important to represent the time, provide their value as 0. The milliseconds must range from 0 to 999. If you do not know the millisecond value, provide it as 0. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue(8, 20, 42, 605);
    ShowMessage("The time considered is " + TimeValue);
}
//---------------------------------------------------------------------------

Since a double-precision number has a decimal section that represents the time of the day, you can assign such a value to a TDateTime variable to initialize a time value. If the integral part of the value is greater than 0, it would represent the number of days. If it is 0, only the time would be recognized as a fraction of the day.

The Time() Function

To get or display the time on your application, you can use the Time() function. You can display it on:

  • An edit box: edtTime->Text = Time();
  • A label: lblCurrent->Caption = “Now is the time: “ + Time();
  • A panel: pnlTime->Caption = “At this time, we have “ + Time();

Converting a String to Time

To convert a string to a time value, use the StrToTime() function whose syntax is:

TDateTime __fastcall StrToTime(const AnsiString S);

This function takes a string as argument. The string must be in a in a valid time format, following the Regional Settings of the Control Panel. For example, in the United States, the components of a time are separated with a colon “:”. The typical formats of a time are:

If the string contains an invalid date, the conversion would fail and the program would throw an error. If the conversion is successful, the function returns a valid time. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm2::btnConvertClick(TObject *Sender)
{
    TDateTime Value = StrToTime(edtSource->Text);
    edtTarget->Text = Value;
}
//---------------------------------------------------------------------------

Converting a Time Value to a String

A time value is, default, recognized and treated as a string whenever necessary. This flexibility allows you to perform transparent conversions from a time to a string values. Therefore, it is perfectly legitimate to write the following assignment:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue("22:32:58");
    AnsiString Right = TimeValue;
    Edit1->Text = Right;
}
//---------------------------------------------------------------------------

This conversion is possible because the AnsiString constructor is overloaded in the TDateTime class. Its syntax is:

__fastcall operator AnsiString() const;

Therefore, to convert a time value to a string, you can simply assign the time to a string variable. You can also explicitly call the overloaded AnsiString() function as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime StartTime("9:05:00 AM");
    AnsiString ToDisplay = StartTime.operator AnsiString();
    Edit1->Text = ToDisplay;
}
//---------------------------------------------------------------------------

The TDateTime class is also equipped with a method that can be used to convert a time value to a string when necessary. The syntax used is:

AnsiString __fastcall TimeString() const;

To convert a time value to a string, declare a TDateTime variable and call the TimeString() method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeValue("22:32:58");
    AnsiString ToDisplay = TimeValue.TimeString();
    Edit1->Text = ToDisplay;
}
//---------------------------------------------------------------------------

Alternatively, to convert a time value to a string, you can use the TimeToStr() function. Its syntax is:

AnsiString __fastcall TimeToStr(System::TDateTime Date);

This function takes one argument, which is the time value that needs to be converted. If the argument is not a valid time value, the conversion would fail and the program would throw an error. If the conversion is successful, the function returns an AnsiString value. 

Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
    AnsiString Current = TimeToStr(Time());
    edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

Converting a Time Value to a Double-Precision Number

A TDateTime time value is a number that represents a fraction of the day on a 24-hour basis. This is quite helpful in algebraic operations.

To convert a time value to a double-precision number, simply cast the time value to a double. In the following example, the current time is converted to double and displayed in an edit box when the user clicks a button on a form:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeX = Time();
    double Value = double(TimeX);
    Edit1->Text = Value;
}
//---------------------------------------------------------------------------

The conversion of a time value to a double-precision number is possible because the double data type was overloaded in the TDateTime to allow this conversion. The syntax of the function used is:

__fastcall operator double() const;

You can use this function transparently as done in the previous example. You can also call it explicitly call it as follows:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime TimeX("09:42:18 AM");
    double Value = TimeX.operator double();
    Edit1->Text  = Value;
}
//---------------------------------------------------------------------------
 

Using Time

 

Displaying the Time

The AnsiString class is highly compatible with the TDateTime class. This flexibility allows any text-based control to be able to display a time value. Thanks to this feature, you do not have to convert a time value in order to display it. For example, to show the current time on the caption of a form, you can just write:

//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
    Caption = Time();
}
//---------------------------------------------------------------------------

This ability is independent of the format of the time; that is, it is independent of the form of initialization or source of the time value.

Decoding a Time

A time variable declared with the TDateTime class is made of an hour, a minute, a second, and a millisecond portions. Decoding a time consists of isolating these components from a valid time value. To perform such an operation, the TDateTime class is equipped with the DecodeTime() method. Its syntax is:

void __fastcall DecodeTime(unsigned short* hour, unsigned short* min,
                           unsigned short* sec, unsigned short* msec) const;

Each component is retrieved using a pointer to an unsigned short. The presence of pointers allows you to pass “empty” variables whose values would be altered by the function and returned with new values.

In the following example, the current time is stored in a TDateTime variable named RightNow. A form is equipped with four Edit controls named edtTime edtHours, edtMinutes, and edtSeconds. Although the mSec argument is required to decode a time value, it was used only during the decoding operation. After calling the function, the hour, the minute, and the second are retrieved and displayed in the corresponding edit boxes:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnDecodeClick(TObject *Sender)
{
    TDateTime RightNow = Time();
    unsigned short Hours, Minutes, Seconds, Milliseconds;
    RightNow.DecodeTime(&Hours, &Minutes, &Seconds, &Milliseconds);
    edtTime->Text    = RightNow;
    edtHours->Text   = Hours;
    edtMinutes->Text = Minutes;
    edtSeconds->Text = Seconds;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------

Besides the TDateTime::DecodeTime() method, the VCL provides a function that can be used to decode a time value. Its syntax is:

void __fastcall DecodeTime(System::TDateTime Time,
			   Word &Hour,
			   Word &Min,
			   Word &Sec,
			   Word &MSec);

The global DecodeTime() function is called in the same circumstances as the TDateTime::DecodeTime() method except that it takes five arguments. The first is and must be a valid TDateTime time value; this could be a time value in a recognizable format or an already initialized variable. If this argument does not carry a valid time, the function will fail and throw an error. The other four arguments are positive integers (unsigned short) passed as reference. This allows the function to alter them and return their changed values.

Encoding a Time

Encoding a time consists of supplying the necessary components of a TDateTime to the compiler to create a valid time value. The function used to perform this operation is:

System::TDateTime __fastcall EncodeTime(Word Hour, Word Min, Word Sec, Word MSec);

This function takes four positive integers (unsigned short) that represent:

  • the hours: the values range from 0 to 23; midnight is 0 while 3 PM is 15
  • the minutes: the values range from 0 to 59;
  • the seconds: the values range from 0 to 59;
  • the milliseconds: the values range from 0 to 999.

Example: the following form is equipped with five Edit controls named edtHours, edtMinutes, edtSeconds, edtMilliseconds, and edtTime. When the user clicks the Encode button named btnEncode, the OnClick event retrieves the hour, the minute, the second, and the millisecond values from their respective edit boxes. The the compiler creates a time from those values and displays the result in the Time edit box:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnEncodeClick(TObject *Sender)
{
    Word Hours, Minutes, Seconds, Milliseconds;

    Hours = edtHours->Text.ToInt();
    Minutes = edtMinutes->Text.ToInt();
    Seconds = edtSeconds->Text.ToInt();
    Milliseconds = edtMilliseconds->Text.ToInt();
    TDateTime Value = EncodeTime(Hours, Minutes, Seconds, Milliseconds);
    edtTime->Text = Value;
}
//---------------------------------------------------------------------------

Replacing a Time Value

To change the time of a TDateTime value, you can use the ReplaceTime() function. Its syntax is:

void __fastcall ReplaceTime(TDateTime &TimeTarget, const TDateTime TimeSource);

The ReplaceTime() function takes two arguments. The second argument is the original time that is used as the time reference. The first argument is the time value that needs to be changed or replaced. The TimeSource argument must be a valid time variable or in a recognizable format; otherwise, the function would fail and throw an error. The TimeTarget argument can be an existing time value of a TDateTime variable. After the function has executed, if successful, the time portions of both arguments would be the same. 

EXAMPLE

Comparison Operations On Time Values

The TDateTime class provides various functions used to perform any type of comparisons between time values. By default, these operations can be applied the same way as done on regular variables. They can also be customized for more detailed comparisons.

The Comparison for Equality

To find out whether two values carry the same time formats, apply the equality comparison, exactly the same way you would proceed for regular variables.

In the following example, two time values are retrieved from two edit boxes for comparison. If both times are the same, a message displays accordingly on a panel:

//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
    TDateTime StartTime = StrToTime(edtStart->Text);
    TDateTime EndTime = StrToTime(edtEnd->Text);

    if( StartTime == EndTime )
        Panel1->Caption = "Same Time";
    else
        Panel1->Caption = "";
}
//---------------------------------------------------------------------------

The equality comparison works on time values thanks the overloaded equality operator on the TDateTime class:

bool __fastcall operator ==(const TDateTime& rhs) const;

The equality comparison works on all components of a time value. If either the hour, the minute, the second, or the AM/PM is not the same the operation renders false. If you want to compare just the hours, you should decode the time values and then perform the comparison on the hours.

The Comparison for Difference

As opposed to the equality operation, you can use the inequality operator to find out whether two dates are different. To do this, simply apply the operator the same way you would do on regular variables. Here is an example following the same logic as above:

//---------------------------------------------------------------------------
void __fastcall TForm1::Panel1Click(TObject *Sender)
{
    TDateTime StartTime = StrToTime(edtStart->Text);
    TDateTime EndTime = StrToTime(edtEnd->Text);

    if( StartTime != EndTime )
        Panel1->Caption = "Different Times";
    else
        Panel1->Caption = "";
}
//---------------------------------------------------------------------------

The difference comparison works on all four entities of a time value. It examines the hours, minutes, seconds, and AM/PM of the values provides on both sides of the operator. If any of both similar components are different, the operation produces a true result. This operation is based on the overloaded != operator whose syntax is:

bool __fastcall operator !=(const TDateTime& rhs) const;

The Comparison for Previous Occurrence

To find out whether a certain time occurs before another, use the “less than” operator “<” the same way you would proceed for a regular variable. In the following example, when the user click the Compare button on a form, the time values on two edit boxes and retrieved and examined. If the time displayed in the Start Shift edit box occurs before the time in the End Shift edit box, a dialog box displays a message accordingly:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
    TDateTime Start = StrToTime(edtStart->Text);
    TDateTime End = StrToTime(edtEnd->Text);

    if( End < Start )
        ShowMessage("Invalid Time Sheet. Please verify accuracy.");
}
//---------------------------------------------------------------------------

The “less than” comparison is based on its overloaded operator in the TDateTime class using the following syntax:

bool __fastcall operator <(const TDateTime& rhs) const;

The Comparison for Previous or Equal Occurrence

The “less than or equal to” operator “<=” is used to check whether a time occurs previous to, or in concordance with, another time. To use this operator on time values, proceed as if you were dealing with regular variables. Here is an example based on the above event:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
    TDateTime Start = StrToTime(edtStart->Text);
    TDateTime End = StrToTime(edtEnd->Text);

    if( End <= Start )
        ShowMessage("Make sure your time sheet is correct.\n"
                    "If you didn't work on this day, "
                    "you don't have to sign the time sheet."
                    "\n\t\t\t\t\t\tThanks");
}
//---------------------------------------------------------------------------

The operator that allows this comparison uses the following syntax:

bool __fastcall operator<=(const TDateTime& rhs) const;

The Comparison for Subsequent Occurrence

To find out whether one time occurs after another, use the “greate than” operator “>”. This operator works the same way it would for a regular variable. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
    TDateTime Start = StrToTime(edtStart->Text);
    TDateTime End = StrToTime(edtEnd->Text);

    if( Start > End )
    {
        lblMessage->Caption = "Your time sheet is not correct.";
        edtStart->SetFocus();
    }
}
//---------------------------------------------------------------------------

The “greater than” operator compare the hours, minutes, seconds, and AM/PM portions of two dates and evaluates if the left date occurred after the right date; in this case, the operator would produce a true Boolean value. This operation is based on its overloaded operator from the TDateTime class. Its syntax is:

bool __fastcall operator >(const TDateTime& rhs) const;

The Comparison for Latter or Same Time

If a time occurs after or in concordance with another time, you can find this out using the “greater than or equal operator. This operator is applied on two valid time values the same way it would be used on regular variables. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnCompareClick(TObject *Sender)
{
    TDateTime Start = StrToTime(edtStart->Text);
    TDateTime End = StrToTime(edtEnd->Text);

    if( Start >= End )
    {
        lblMessage->Caption = "Your time sheet is not correct.";
        edtStart->SetFocus();
    }
}
//---------------------------------------------------------------------------

This comparison is possible thanks to the following overloaded operator in the TDateTime class:

bool __fastcall operator >=(const TDateTime& rhs) const;

Controlling Time Display

The TDateTime class and the systdate.h file provide various techniques to control how the time displays. Fundamentally the time displays according to the settings of the Control Panel. There are two main functions for this purpose.

The TDateTime class is equipped with the FormatString() function whose syntax is:

AnsiString __fastcall FormatString(const AnsiString& Format);

This function takes, as an argument, a string that specifies how the components of the time value should display. The VCL provides an alternative function to apply the same technique.; Its syntax is:

AnsiString __fastcall FormatTDateTime(const AnsiString Format,
                                      System::TDateTime Time);

When calling the FormaTDateTime() function, you must pass two arguments. The Time argument represents a time value or a variable that holds a valid time value. The Format argument is a string that specifies how the time of the Time argument should display.

Displaying in Default Format

By default, the FormatDateTime() and the TDateTime::FormatString() functions follow the format set by the computer’s Regional Settings of the Control Panel, which usually ignores the 0 for hours less than 10.

To display the time using the default format, call the TDateTime::FormatString() method and provide the Format argument as “c”. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime RightNow = Time();
    RightNow.FormatString("c");

    Edit1->Text = RightNow;
}
//---------------------------------------------------------------------------
 

Displaying the Leading Zero

When the hour portion of a time value is less than 10, you can control whether to display the leading zero. This also applies to the minutes and the seconds. Each of these entities provide two formats to take care of this. The syntax used to display the time is

hh:nn:ss AM/PM

The hh, nn, and ss portions are not case sensitive.

To ignore a leading zero when an hour less than 10 displays, use only h for the hour portion. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime RightNow = Time();

    Edit1->Text = RightNow.FormatString("h:nn:ss AM/PM");
}
//---------------------------------------------------------------------------

To display the leading zero, use the hh format for the hour portion. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime RightNow = Time();

    Edit1->Text = RightNow.FormatString("hh:nn:ss AM/PM");
}
//---------------------------------------------------------------------------

The rule to display or not display the leading zero for the minutes is the same. To avoid the leading zero, use only one n when displaying the time. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTimeClick(TObject *Sender)
{
    TDateTime TimeX("08:05:52 AM");

    // Displaying the minutes without the leading zero
    edtStart->Text = TimeX.FormatString("HH:n:ss AM/PM");
    // Displaying the minutes with the leading zero
    edtEnd->Text = TimeX.FormatString("hh:nn:ss AM/PM");
}
//---------------------------------------------------------------------------

These same rules apply for the seconds portions of the time display.

The AM/PM portion is case sensitive. This allows you display it in uppercase or in lowercase. To display the AM/PM section in lowercase, type am/pm or ampm in the AM/PM section. On the other hand, to display it in uppercase, type it as AM/PM or AMPM. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnTimeClick(TObject *Sender)
{
    TDateTime TimeX("18:05:52");

    // Displaying the AM/PM portion in lowercase
    edtStart->Text = TimeX.FormatString("hh:n:ss am/pm");
    // Displaying the AMPM portion in uppercase
    edtEnd->Text = TimeX.FormatString("hh:nn:ss AM/PM");
}
//---------------------------------------------------------------------------

Combining Date and Time

 

Fundamental Functions: Now()

C++ Builder provides a function that combines date and time. This function, called Now(), can be used to display its value on:

  • An edit box: edtNow->Text = “Date and Time: “ + Now();
  • A label: lblNow->Caption = “Now: “ + Now();
  • A form’s caption: Caption = Now();

Converting a String to Date and Time

To convert a string to a valid date and time, use the StrToDateTime() function. This function follows the same rules as the StrToDate() function. Its syntax is:

TDateTime __fastcall StrToDateTime(const AnsiString S);

This function takes a string as argument. The string must have a valid TDateTime format; otherwise, the operation would faild. If everything works fine, after converting the string, the function returns a valid TDateTime value.

In the following example, a form is created with a MaskEdit control named edtSource, an Edit control named edtTarget, two Button controls named btnConvert and btnExit. The EditMask of the MaskEdit control is configured as follows:

!99/99/0000 !90:00:00 >LL;1;_

Here is the OnClick event of the Convert button:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
    TDateTime Current = StrToDateTime(edtSource->Text);
    edtTarget->Text = Current;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::btnExitClick(TObject *Sender)
{
    Close();
}
//---------------------------------------------------------------------------
 

Converting a Date and Time to a String

To convert a date and time value to a string, use the DateTimeToStr(). Its syntax is:

AnsiString __fastcall DateTimeToStr(System::TDateTime Date);

This function takes, as argument, a valid TDateTime variable or value. If the argument is not a valid date and time value, an error would result. After performing the conversion on the date and time value, the function returns the value as a string.

In the following example, when the user clicks a button named btnConvert, the event uses the Now() function to retrieve the current date and time then converts it to string and displays the string in an Edit control named edtTarget:

//---------------------------------------------------------------------------
void __fastcall TForm1::btnConvertClick(TObject *Sender)
{
    AnsiString Current = DateTimeToStr(Now());
    edtTarget->Text = Current;
}
//---------------------------------------------------------------------------

An alternative method to converting a date and time value to a string consists of using the TDateTime::DateTimeString() method. Its syntax:

AnsiString __fastcall DateTimeString() const;

This function does not need an argument. To use it, declare a TDateTime date variable and call the DateTimeString() method. Here is an example:

//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
    TDateTime Current = Now();
    AnsiString Right = Current.DateTimeString();
    Edit1->Text = Right;
}
//---------------------------------------------------------------------------
 

Copyright © 2002-2006 Yevol