Fundamentals of Date/Time Values

Introduction

To support the combination of a date and a time values as one unit, the .NET Framework provides a structure named DateTime. To create a date or a time, or a combination of a date and time value, you can first declare a DateTime variable. To assist you with initializing the variable, the DateTime structure is equipped with various constructors.

Practical LearningPractical Learning: Introducing Tool Bars

  1. Start Microsoft Visual Studio
  2. Create a Windows Forms App application named Exercise11

Crating a Date/Time Object

The default constructor or the DateTime structure allows you to create a date/time object without specifying its details. To start, you can declare a DateTime as follows:

DateTime tmArrival;

Presenting a Date/Time Value

To let you display a DateTime value, the DateTime structure is equipped with the ToString() method that is overloaded with various versions. Its simplest syntax is:

public override string ToString();

This version uses the default date format of the user's computer. Otherwise other versions are available.

Another way to display a DateTime value is to call the string.Format() method in which you would create {} placeholders. Beside the ToString() and the string.Format() method, you can use string interpolation to display a DateTime value.

Creating a Date/Time Combination

After declaring a DateTime variable, you can initialize it. You have many options.

To let you create a value that is a combination of date and time values, the DateTime structure is equipped the following constructor:

public DateTime (int year, int month, int day, int hour, int minute, int second);

This constructor takes six arguments. Therefore, to create a unit with the date and time values, pass the year, the month, the day, the hours, the minutes, and the seconds respectively. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    DateTime occurrence = new DateTime(2024, 10, 6, 18, 45, 22);

    txtInitialOccurrence.Text = occurrence.ToString();
}

Creating a Date Object

As you may know already (from our introduction to the DateOnly structure), you can create a date value as a combination of a year, a month, and a day. To support dates, the DateTime structure is equipped with the following constructor:

public DateTime(int year, int month, int day);

You can use this constructor to create a DateTime value where the time section is not important. Here is an example:

private void Exercise_Load(object sender, EventArgs e)
{
    DateTime independence = new DateTime(1776, 7, 4);

    txtIndependence.Text = independence.ToString();
}

If you use that contructor, the time section is set to midnight of the date passed as argument. The above code would produce:

Creating a Date Object

A Date/Time as a Type

Introduction

The DateTime structure is primarily a type like any other.

A Date/Time Field

A field of a class, a record, or a structure can be of a DateTime type. You can declare the variable in the body of the type. You can initialize it immediately. Here is an example:

namespace CommunityHospital
{
    internal class Surgery
    {
        private DateTime _date = new DateTime();
        public Anesthesiologist? Controller { get; set; }
        public Surgeon? OnDuty { get; set; } 
    }

    public record Anesthesiologist { }
    public class Surgeon { }
}

You can also initialize a DateTime field in a method or in a constructor.

A Date/Time Property

A class, a structure, or a record can have one or more DateTime properties. There is nothing magical to do; just proceed as done with another other type.

You can also create a DateTime property in a positional parameter record. Here is an example:

namespace TimeAndDate
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            TrafficTicket tt = new TrafficTicket(294_805, new DateTime(2022, 10, 6, 22, 46, 0), 75);

            lbxViolation.Items.Add($"Ticket Number: {tt.TicketNumber}");
            lbxViolation.Items.Add($"Date/Time Occurrence: {tt.ViolationTime}");
            lbxViolation.Items.Add(string.Format("Amount Owed: {0}", tt.AmountOwed.ToString("C")));
        }
    }

    public record TrafficTicket(long TicketNumber, DateTime? ViolationTime, double AmountOwed)
    {
    	bool paid = false;

        public void SendNotification()
        {
            if(!paid)
            {
                MessageBox.Show("Your ticket payment is late " +
                                "(and your driver's license is about to be suspended. " +
                                "Can you afford to have your driver's license revoked?",
                                "Traffic Tickets System",
                                MessageBoxButtons.YesNo, MessageBoxIcon.Question);
            }
        }
    }
}

A List of Date/Time Values

You can create a list of dates values, times values, or a list of a combination of those. Probably the simplest way you can proceed is to create an array of those values. You can initialize each item of the list by using one of the constructors of the DateTime structure. Here is an example of an array of date/time values:

DateTime[] dateOfAdmissionToFederation = new DateTime[]
{
    new DateTime(1823, 12, 20), new DateTime(1824,  2,  7), new DateTime(1823, 12, 22), new DateTime(1824,  5,  7),
    new DateTime(1824,  7,  6), new DateTime(1952,  1, 16), new DateTime(1917,  1, 26), new DateTime(1823, 12, 21),
    new DateTime(1823, 12, 21), new DateTime(1869,  4, 17), new DateTime(1824,  1, 10), new DateTime(1857,  2,  5),
};

In the same way, if you are using a VisualBasic.Collection list, you can create a list of date/time values, or you can create a list of objects where one of the sections of each item is a date/time value.

Characteristics of a Date/Time Value

Characteristics of a Date Value

A DateTime object supports the same characteristics we reviewed for the DateOnly structure. These include:

The Default Date/Time Values

The default constructor of the DateTime structure initializes the date to January 1st, 0001 and the time at midnight (01:01:01). Here is an example that shows it:

namespace TimeAndDateValues
    {
        public partial class Exercise : Form
        {
            public Exercise()
            {
                InitializeComponent();
            }
    
            private void Exercise_Load(object sender, EventArgs e)
            {
                DateTime dtDefault = new DateTime();

                txtDefault.Text = tm.ToString();
            }
        }
    }

This would produce:

Creating a Date Object

The Minimum Date Value

This also means that the lowest date and time values that a DateTime object can hold is January 1st, 0001 at 00:00:00 (midnight). This value is represented by the MinValue constant member of the DateTime structure.

The Maximum Date Value

The highest date and time that a DateTime object can hold in the structure is called MaxValue and it is set at December 31, 9999.

Requesting Date a Value

As done with the regular numbers, you can request a date value from the user. To support this operation, the DateTime structure is equipped with the same Parse method that we reviewed for the other structures of the C# data type. This method is overloaded. The simplest version uses the following syntax:

public static DateTime Parse (string s);

To use this method, pass a string that may contain a date, a time, or a date/time value. Here is an example:

private void btnValidate_Click(object sender, EventArgs e)
{
    DateTime dtStartWorkTime = new DateTime();
    
    try
    {
        dtStartWorkTime = DateTime.Parse(txtStartWorkTime.Text);
    }
    catch (Exception ex) when (ex is FormatException fe)
    {
        MessageBox.Show("The value you entered for the start work date and time is not valid. "
                        + Environment.NewLine +
                        "The error produced is: " + fe.Message, "Human Resources",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    }
}

Here is an example of running the application:

Requesting Date a Value

By default, if you request only a date from the user and the user enters a valid date, the compiler would add the midnight value to the date. If you request only the time from the user and the user enters a valid time, the compiler would add the current date to the value.

Dates and Times Formatting

Date Formatting

The DateTime structure supports the same techniques as the DateOnly structure to indicate how the date side of a DateTime value should appear. These include:

Time Formatting

The DateTime structure supports the same techniques as the DateOnly structure to indicate how the time display. These include:

Combining Date and Time

The Current Date and Time

When a user starts a computer and while using it, the computer keeps a date and time values referred to as local date and time or system date and time. Depending on your application, at one time you may need to get one or both of these pieces of information. It is important to know that the computer, not you, controls this information (but you can programmatically change it if you want). To support both, the DateTime structure is equipped with a static property named Now. This property holds the year, the month, the day, the name of the day, the hour, the minute, and the second. Here is an example of accessing it:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            txtNow.Text = DateTime.Now.ToString();
        }
    }
}

Here is an example of running the program:

The Current Date and Time

Today's Date at Midnight

To let you know today's date (the date of the computer), the DateTime structure provides a static property named Today. This property holds the date of the computer at 0:00:00 (midnight). Here is an example of accessing this property:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            txtToday.Text = DateTime.Today.ToString();
        }
    }
}

Here is an example of running the program:

>

Today's Date at Midnight

Formatting Date and Time Combinations

Although the DateTime structure is equipped to produce default values of a date and time in combination, you can use the formats we have reviewed to create your own date, in the sequences of your choice, such as a time preceding a date, a value providing only the month and the minutes, etc.

The Time of a Date/Time Object

The Time of Day of a Time Value

As seen so far, a DateTime variable always holds both a date and a time portions. In your application, you may want to get only the time of the variable. To support this, the DateTime structure is equipped with a property named TimeOfDay. This property produces the time value of an existing DateTime object. Here is an example of using it:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void Exercise_Load(object sender, EventArgs e)
        {
            DateTime time = new DateTime(2002, 4, 22, 16, 8, 44);

            txtTimeOfDay.Text = time.TimeOfDay.ToString();   
        }
    }
}

This would produce:

The Time of Day of a Time Value

Retrieving a Time Value

In a certain application, you may want the visitor to provide a time value. A valid time can follow the format hh:nn AM/PM or hh:nn:ss or one of the valid combinations. When requesting a time from the user, in case the user is not familiar with the rules (and you should assume that the user doesn't know them), specify what formula the user should follow.

To get the hour portion of an existing DateTime object, you can access its Hour property. To retrieve the minute side of a time value, access its Minute property. If you want to know the second value of a DateTime variable, you can call its Second property. In the same way, you can get the millisecond value of a time by accessing its Millisecond property.

Windows Controls: A Timer

Introduction

A timer is a non-spatial object that uses recurring lapses of time in a computer or in your application. To work, every lapse of period, the control fires an event.

Users do not see nor do they use a timer as a control. As a programmer, you decide if, why, when, and how to use this control.

To support timers, the .NET Framework provides a class named Timer. You can use that class to programmatically create a timer. To let you visually add a timer to your application, the Toolbox is equipped with a button named Timer. It is available in the Components section of the Toolbox. You can click that control and click your form. The timer is not a visual control. Therefore, if you visually add it to your form, it would only be represented by a button below the form.

Characteristics of a Timer: A Tick Event

A timer is an object used to count lapses of time and send a message when it has finished counting. Each count is called a tick. When a tick occurs, the control fires an event named Tick. This Tick event is of type EventArgs, meaning that it doesn't provide more information than to let you know that a lapse has occurred. Here is an example of implementing that event:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        Timer tmrFlash;

        public Exercise()
        {
            InitializeComponent();
        }

        void InitializeComponent()
        {
            tmrFlash = new  Timer ();
            tmrFlash.Tick += new EventHandler(btnFlashTick);

            Text = "Text Flasher";
            Size = new System.Drawing.Size(435, 88);
        }

        void btnFlashTick(object sender, EventArgs e)
        {
        }
    }
}

The amount of time allocated for counting is called an interval and it is represented by the Interval property. The Interval property is a very important characteristic of the Timer control because it measures and controls the total time needed to perform a complete count. The Interval is measured in milliseconds. Like any counter, the lower the value, the faster the count, and the higher the value, the longer the count. The amount of interval you specify will depend on what you are trying to do. Here is an example of specifying the interval:

void InitializeComponent()
{
    tmrFlash = new  Timer ();
    tmrFlash.Interval = 500;
    tmrFlash.Tick += new EventHandler(btnFlashTick);
}

Enabling a Timer

In order for a timer to count, you must tell it when it should start counting. In some applications, you may want the control to work full-time while in some other applications, you may want the control to work only in response to an intermediate event. The ability to stop and start a Timer control can be set using a Boolean property named Enabled. Here is an example of enabling a timer:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        Timer tmrFlash;
        Label lblFlash;

        public Exercise()
        {
            InitializeComponent();
        }

        void InitializeComponent()
        {
            tmrFlash = new  Timer();
            tmrFlash.Interval = 500;
            tmrFlash.Enabled = true;
            tmrFlash.Tick += new EventHandler(btnFlashTick);

            lblFlash = new Label();
            lblFlash.AutoSize = true;
            lblFlash.Text = "C# Programming is Fun!!!";
            lblFlash.Font = new System.Drawing.Font("Square721 BT", 24F);
            lblFlash.ForeColor = System.Drawing.Color.Blue;
            lblFlash.Location = new System.Drawing.Point(12, 10);

            Text = "Text Flasher";
            Size = new System.Drawing.Size(435, 88);
            Controls.Add(lblFlash);
        }

        void btnFlashTick(object sender, EventArgs e)
        {
            if (lblFlash.Text == "C# Programming is Fun!!!")
                lblFlash.Text = "";
        	else
                lblFlash.Text = "C# Programming is Fun!!!";
	  }
    }
}

Starting a Timer

When, or as soon as, this property is set to true, the control starts counting. You can also make it start by calling the Timer.Start() method. Its syntax is:

public void Start();

Stopping a Timer

If, when, or as soon as, the Enabled property is set to false, the control stops and resets its counter to 0. You can also stop the timer by calling the Timer.Stop() method. Its syntax is:

public void Stop();

Accessories for Dates Operations

Introduction

Like value types and strings, dates support various types of operations. These include adding a value to a date to get a new date, subtracting a value from a date, extracting a certain value from a date, etc.

The Leap Year

A leap year is a year in which the month of February has 29 days. To let you find out whether a year is a leap year, the DateTime structure is equipped with a static method named IsLeapYear. The syntax of this method is:

public static bool IsLeapYear(int year);

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

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void mcMeeting_DateChanged(object sender, EventArgs e)
        {
            DateTime meeting = mcMeeting.SelectionStart;

            if(DateTime.IsLeapYear(meeting.Year))
            {
                MessageBox.Show("The year of the date you selected is a leap year.",
                                "Meetings",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            else
            {
                MessageBox.Show("From the date you selected, the year is not a leap year.",
                                "Meetings",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
        }
    }
}

Here are two reactions from selecting a date in a calendar:

 Leap Year

A Time Span

Common operations on dates include adding days to a date, subtracting months from a date, adding years, comparing dates to find out whether one occurs before another, etc. To perform some of these operations, a unit called an interval is considered as part of a date. A date interval is the number of days, months, or years that have elapsed, or would elapse, from one starting date to another ending date. Once you have specified this interval, you can then apply it to a date with the operation of your choice.

To support the ability to perform operations on dates, the .NET Framework provides a structure named TimeSpan. This structure is equipped with various members that would be applied on the TimeSpan structure. The value produced by this structure is then applied to a DateTime object. To create a date interval, declare a TimeSpan variable and initialize it with the desired value(s). To make this possible, the TimeSpan structure is equipped with various constructors.

Day-Based Operations

Adding Days to a Date Value

With the DateTime structure, you can add some days to an existing date. To support this, the DateTime structure is equipped with a method named AddDays. Its syntax is:

public DateTime AddDays(int days);

Here is an example of calling this method:

private void btnAdd_Click(object sender, EventArgs e)
{
    int days = 0;
    DateTime startDate = mcStartDate.SelectionStart;
            
    try
    {
        days = int.Parse(txtDays.Text);
    }
    catch(Exception ex) when (ex is FormatException fe)
    {
        MessageBox.Show("The value you entered for the number of days is not valid." + 
                        Environment.NewLine + 
                        "The error produced is: " + fe.Message,
                        "date/Time Values",
                        MessageBoxButtons.OK, MessageBoxIcon.Information);
    }

    DateTime endDate = startDate.AddDays(days);

    mcEndDate.SelectionStart = endDate;
}

Here is an example of running the program:

Adding Days to a Date Value

Adding Days to a Date Value

Adding Days to a Date Value

If you pass a positive value to the DateTime.AddDays() method, a number of days is added to the DateTime variable.

Adding a Time Span Value

To allow you to add a date-based value to a date, the DateTime structure is equipped with a method named Add. Its syntax is:

public DateTime Add (TimeSpan value);

This method takes a TimeSpan argument and it returns a DateTime object. To use it, create a TimeSpan object that contains the value(s) to add. Here is an example:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            int days = 0;
            DateTime startDate = mcStartDate.SelectionStart;
            
            try
            {
                days = int.Parse(txtDays.Text);
            }
            catch(Exception ex) when (ex is FormatException fe)
            {
                MessageBox.Show("The value you entered for the number of days is not valid." + 
                                Environment.NewLine + 
                                "The error produced is: " + fe.Message,
                                "date/Time Values",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            // Declare a TimeSpan variable and pass the number of days to it
            TimeSpan ts = new TimeSpan(days, 0, 0, 0);
            // Pass the TimeSpan object to the date
            DateTime endDate = startDate.Add(ts);

            mcEndDate.SelectionStart = endDate;
        }
    }
}

Here is an example of running the application:

Subtracting Days from a Date Value

To let you subtract date values, the DateTime structure is equipped with an overloaded method named Subtract. The syntax of one of them takes a DateTime object:

public TimeSpan Subtract(DateTime value);

When calling this version, create and pass a DateTime object. This version produces a TimeSpan object. From that returned object, you can identify the value that was produced.

As an alternative to the DateTime.Subtract() method, you can call the DateTime.Add() method. If you want to subtract some days from a date, pass a negative value to the DateTime.AddDays() method. This method is able to figure out the year before, the month before, the day before, the day after, the month after, and the year after the designated date.

One of the constructors of the TimeSpan structure takes four arguments. Its syntax is:

public TimeSpan(int days, int hours, int minutes, int seconds);

The first argument of this constructor represents the number of days. If you are planning to add a number of days to a date, pass a positive integer as the first argument. If you want to subtract a date, pass a negative value. If you want to add only a number of days, pass only this argument.

Subtracting a Time Span Value

The other version of the DateTime.Subtract() method takes a TimeSpan object as argument:

public DateTime Subtract(TimeSpan value);

This time, pass a TimeSpan object to the method. As an alternative, the DateTime structure makes it possible to subtract a value from a date. To do this, pass a negative value to the DateTime.Add() method. This would produce a new DateTime object. Here is an example:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            int days = 0;
            DateTime startDate = mcStartDate.SelectionStart;
            
            try
            {
                days = int.Parse(txtDays.Text);
            }
            catch(Exception ex) when (ex is FormatException fe)
            {
                MessageBox.Show("The value you entered for the number of days is not valid." + 
                                Environment.NewLine + 
                                "The error produced is: " + fe.Message,
                                "date/Time Values",
                                MessageBoxButtons.OK, MessageBoxIcon.Information);
            }

            TimeSpan ts = new TimeSpan(-days, 0, 0, 0);
            // Pass the TimeSpan object to the date
            DateTime endDate = startDate.Add(ts);

            mcEndDate.SelectionStart = endDate;
        }
    }
}

Here is an example of running the application:

Month-Based Operations

Adding Months to a Date Value

To let you add a number of months to a date, the DateTime class is equipped with a method named AddMonths. Its syntax is:

public DateTime AddMonths(int months);

This method takes one argument as a number of months. If you pass the argument with a positive value, the months are added to the date.

Subtracting Months to a Date

To subtract a number of months from a date, you can call the DateTime.AddMonths() method. If you pass the argument with a negative value, the number of months is subtracted from the date.

Year-Based Operations

Adding or Subtracting Years to a Date

To get the date a few years before or after a known date, you can add years to, or subtract years from, a known date. To support this operation, the DateTime class provides a method named AddYears. Its syntax is:

public DateTime AddYears(int years);

The argument passed to the method is the number of years. A positive value (or a negative value) adds (or subtracts) the number of years to (or from) the date.

Logical Operations on Dates

Using the logical operators we reviewed for primitive types, you can compare the values of dates for equality, differences, lower or greater values. To support these operations, the DateTime structure has the logical operators configured appropriately.

To compare two dates, apply the desired Boolean operator the same way you would proceed for two variables of primitive types. Here is an example:

namespace DateAndTime
{
    public partial class Exercise : Form
    {
        public Exercise()
        {
            InitializeComponent();
        }

        private void btnCompare_Click(object sender, EventArgs e)
        {
            DateTime startDate = mcStartDate.SelectionStart;
            DateTime endDate   = mcEndDate.SelectionStart;

            if (startDate < endDate)
            {
                lblComparisonResult.Text = string.Format($"{startDate} occurs before {endDate}");
            }
        }
    }
}

Here is an example of running the application:

Logical Operations on Dates

Practical LearningPractical Learning: Ending the Lesson


Previous Copyright © 2001-2024, FunctionX Friday 10 June 2022 Next