Operations on Date Values
Operations on Date Values
Windows Controls and Dates Values
Introduction
You ahould always make sure your graphical application is as user-friendly. When it comes to date values, you should make sure to assist your users so they can provide only valid values, and in the previous lesson, we saw that date values most follow strict rules. To assist you, the .NET Framework provides various Windows controls specially made for date values, making it practically impossible for the user to provide invalid date values.
Practical Learning: Introducing Operations on Date Values
namespace GasUtilityCompany3 { public interface IUtilityMeter { string MeterNumber { get; set; } string Make { get; set; } string Model { get; set; } } }
using System; namespace GasUtilityCompany31 { public class GasMeter : IUtilityMeter { public string MeterNumber { get; set; } public string Make { get; set; } public string Model { get; set; } public int CounterValue { get; set; } } }
namespace GasUtilityCompany3 { public class Customer { public string AccountNumber { get; set; } public string MeterNumber { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public string Address { get; set; } public string City { get; set; } public string County { get; set; } public string State { get; set; } public string ZIPCode { get; set; } } }
Control | (Name) | Text | Other Properties |
Label | Customer Account Information | BackColor: Gray |
|
Label | Account #: | ||
TextBox | txtAccountNumber | ||
Label | Customer Name: | ||
TextBox | txtCustomerName | ||
Label | Address | ||
TextBox | txtAddress | ||
TextBox | txtCity | ||
TextBox | txtCounty | ||
TextBox | txtState | ||
TextBox | txtZIPCode | ||
Label | Meter Information | BackColor: Gray |
|
Label | Meter Details: | ||
TextBox | txtMeterNumber | ||
TextBox | txtMeterDetails | ||
Label | Meter Reading | ||
Label | _________________________ | ||
Label | Counter Reading Start: | ||
TextBox | txtCounterReadingStart | TextAlign: Right | |
Label | Counter Reading End: | ||
TextBox | txtCounterReadingEnd | TextAlign: Right |
using System; using System.Windows.Forms; namespace GasUtilityCompany32 { public partial class Form1 : Form { GasMeter[] meters = new GasMeter[7]; Customer[] customers = new Customer[5]; public Form1() { InitializeComponent(); } private void txtAccountNumber_Leave(object sender, EventArgs e) { /* This is the list of utility meters used by the company. * Every device has a unique meter number. */ meters = new GasMeter[] { new GasMeter() { MeterNumber = "582741-38", Make = "Sinton International", Model = "D-244", CounterValue = 138 }, new GasMeter() { MeterNumber = "293847-27", Make = "Archimeda", Model = "LP2066", CounterValue = 2866 }, new GasMeter() { MeterNumber = "928731-59", Make = "EnvioSmart", Model = "84-D9703", CounterValue = 8016 }, new GasMeter() { MeterNumber = "520246-85", Make = "Garland Worldwide", Model = "GFH-2260", CounterValue = 22683 }, new GasMeter() { MeterNumber = "797047-27", Make = "Archimeda", Model = "LP2066", CounterValue = 725 }, new GasMeter() { MeterNumber = "425837-14", Make = "EnvioSmart", Model = "28-G4428", CounterValue = 6114 }, new GasMeter() { MeterNumber = "162460-82", Make = "Archimeda", Model = "Di8000", CounterValue = 15502 }, new GasMeter() { MeterNumber = "864085-92", Make = "Sinton International", Model = "D-244", CounterValue = 83 } }; /* This si the list of customers who use the gas produced and distributed by the company. * Every customer uses a utility metter number. That number must (1) correspond to a gas * meter from the above list, (2) the gas meter a customer uses must be unique among the other customers. */ customers = new Customer[] { new Customer(){ AccountNumber = "620-9720-824", MeterNumber = "293847-27", FirstName = "Jefferey", LastName = "Parriot", Address = "688 Gorman Str", City = "Rockville", County = "Montgomery", State = "MD", ZIPCode = "20856" }, new Customer(){ AccountNumber = "4482-1397-851", MeterNumber = "425837-14", FirstName = "Christopher", LastName = "McGee", Address = "3316 Sanderson Rd", City = "Alexandria", County = "", State = "VA", ZIPCode = "22312" }, new Customer(){ AccountNumber = "852-9360-597", MeterNumber = "582741-38", FirstName = "Sandra", LastName = "Rhodes", Address = "11158 Grattos Ave", City = "Hyattsville", County = "Prince George", State = "MD", ZIPCode = "20783" }, new Customer(){ AccountNumber = "209-5384-805", MeterNumber = "928731-59", FirstName = "Marco", LastName = "Ramos", Address = "9012 Jefferson Crt", City = "Washington", County = "", State = "DC", ZIPCode = "20012" }, new Customer(){ AccountNumber = "972-3848-393", MeterNumber = "797047-27", FirstName = "Gabrielle", LastName = "Bayley", Address = "799 Boomerang Str", City = "Columbia", County = "Howard", State = "MD", ZIPCode = "21042" } }; // Request/Get the customer's account number from the user string acntNbr = txtAccountNumber.Text; // We will need to identify the gas meter that a customer is using. string striMeterNumber = string.Empty; // When the user has typed a customer's account number, visit each of the customers accounts. for (int i = 0; i <= customers.Length - 1; i++) { // Find out if there is a customer record that has the accont number the user had entered. if (customers[i].AccountNumber == acntNbr) { // If the user entered a valid customer's account, display the information of that customer txtCustomerName.Text = string.Format("{0}, {1}", customers[i].LastName, customers[i].FirstName); txtAddress.Text = customers[i].Address; txtCity.Text = customers[i].City; txtCounty.Text = customers[i].County; txtState.Text = customers[i].State; txtZIPCode.Text = customers[i].ZIPCode; // Get the gas meter number the user is using striMeterNumber = customers[i].MeterNumber; // Since you found the customer record, stop looking break; } } // Get a list of all the gas meters that the company is using and check each of them. for (int i = 0; i <= meters.Length - 1; i++) { // If you find a gas meter that corresponds to the customer's account, ... if (meters[i].MeterNumber == striMeterNumber) { // Display a summary of that gas meter txtMeterNumber.Text = meters[i].MeterNumber; txtMeterDetails.Text = string.Format("Meter: {0} {1}", meters[i].Make, meters[i].Model); txtCounterReadingStart.Text = meters[i].CounterValue.ToString(); // Since you found the customer's gas meter, stop looking break; } } } } }
Labels and Text Boxes
As you may know already, the label and the text box are the primary Windows controls used in an application. They are also the vaguest controls because they can deal with almost any value. When it comes to a date, if you are requesting such a value, in the caption of the label, you can include the format you want the user to use. Here is an example:
The Calendar Windows Control
Introduction
The calendar is a Windows control that presents a calendar on a form and allows the user to select a date:
Creating a Calendar
To support the calendar control, the .NET Frameworok provides a class named MonthCalendar. To add a calendar to your application, in the Toolbox, click MonthCalendar and click the form. The characteristics of the control can be managed through the MonthCalendar class. Those characteristics can be visually accessed in the Properties window.
Practical Learning: Introducing the Calendar Control
Control | (Name) | Text |
Label | Reading Start Date | |
Label | Reading End Date | |
MonthCalendar | mcReadingStartDate | |
MonthCalendar | mcReadingEndDate |
using System; namespace GasUtilityCompany32 { class GasMeter :IUtilityMeter { public string MeterNumber { get; set; } public string Make { get; set; } public string Model { get; set; } public DateTime MeterReadingDate { get; set; } public int CounterValue { get; set; } } }
Selecting a Date
A calendar control displays the days of a selected month. The control also displays the remaining days, if any, of the first week of the currently selected month; that is, the days of the previous month that share the week with the first day of the first week of the selected month. The control also displays the first days of the subsequent month that share the week with the last day of the current month.
To use the calendar control, the user can click a date, whether a date from the current month or a day of the other (previous and next) month. To support the date selected on the calendar, the MonthCalendar class is equipped with a property named SelectionStart.
When the user has clicked a date to select it, the control fires a DateSelected event. The DateSelected event is of type DateRangeEventArgs.
You too can programmatically select a date on the calendar control. To do this, assign a valid DateTime value to both the SelectionStart and the SelectionEnd properties.
Practical Learning: Selecting a Date
using System; using System.Windows.Forms; namespace GasUtilityCompany31 { public partial class Form1 : Form { GasMeter[] meters = new GasMeter[7]; Customer[] customers = new Customer[5]; public Form1() { InitializeComponent(); } private void txtAccountNumber_Leave(object sender, EventArgs e) { /* This is the list of utility meters used by the company. * Every device has a unique meter number. */ meters = new GasMeter[] { new GasMeter() { MeterNumber = "582741-38", Make = "Sinton International", Model = "D-244", MeterReadingDate = new DateTime(2021, 5, 10), CounterValue = 138 }, new GasMeter() { MeterNumber = "293847-27", Make = "Archimeda", Model = "LP2066", MeterReadingDate = new DateTime(2021, 8, 3), CounterValue = 2866 }, new GasMeter() { MeterNumber = "928731-59", Make = "EnvioSmart", Model = "84-D9703", MeterReadingDate = new DateTime(2020, 12, 8), CounterValue = 8016 }, new GasMeter() { MeterNumber = "520246-85", Make = "Garland Worldwide", Model = "GFH-2260", MeterReadingDate = new DateTime(2021, 5, 21), CounterValue = 22683 }, new GasMeter() { MeterNumber = "797047-27", Make = "Archimeda", Model = "LP2066", MeterReadingDate = new DateTime(2021, 10, 4), CounterValue = 725 }, new GasMeter() { MeterNumber = "425837-14", Make = "EnvioSmart", Model = "28-G4428", MeterReadingDate = new DateTime(2021, 1, 1), CounterValue = 6114 }, new GasMeter() { MeterNumber = "162460-82", Make = "Archimeda", Model = "Di8000", MeterReadingDate = new DateTime(2020, 6, 3), CounterValue = 15502 }, new GasMeter() { MeterNumber = "864085-92", Make = "Sinton International", Model = "D-244", MeterReadingDate = new DateTime(2021, 10, 5), CounterValue = 83 } }; /* This si the list of customers who use the gas produced and distributed by the company. * Every customer uses a utility metter number. That number must (1) correspond to a gas * meter from the above list, (2) the gas meter a customer uses must be unique among the other customers. */ customers = new Customer[] { new Customer(){ AccountNumber = "620-9720-824", MeterNumber = "293847-27", FirstName = "Jefferey", LastName = "Parriot", Address = "688 Gorman Str", City = "Rockville", County = "Montgomery", State = "MD", ZIPCode = "20856" }, new Customer(){ AccountNumber = "482-1397-851", MeterNumber = "425837-14", FirstName = "Christopher", LastName = "McGee", Address = "3316 Sanderson Rd", City = "Alexandria", County = "", State = "VA", ZIPCode = "22312" }, new Customer(){ AccountNumber = "852-9360-597", MeterNumber = "582741-38", FirstName = "Sandra", LastName = "Rhodes", Address = "11158 Grattos Ave", City = "Hyattsville", County = "Prince George", State = "MD", ZIPCode = "20783" }, new Customer(){ AccountNumber = "209-5384-805", MeterNumber = "928731-59", FirstName = "Marco", LastName = "Ramos", Address = "9012 Jefferson Crt", City = "Washington", County = "", State = "DC", ZIPCode = "20012" }, new Customer(){ AccountNumber = "972-3848-393", MeterNumber = "797047-27", FirstName = "Gabrielle", LastName = "Bayley", Address = "799 Boomerang Str", City = "Columbia", County = "Howard", State = "MD", ZIPCode = "21042" } }; // Request the customer's account number from the user string acntNbr = txtAccountNumber.Text; // We will need to identify the gas meter that a customer is using. string striMeterNumber = string.Empty; // When the user has typed a customer's account number, visit each of the customers accounts. for (int i = 0; i <= customers.Length - 1; i++) { // Find out if there is a customer record that has the accont number the user had entered. if (customers[i].AccountNumber == acntNbr) { // If the user entered a valid customer's account, display the information of that customer txtCustomerName.Text = string.Format("{0}, {1}", customers[i].LastName, customers[i].FirstName); txtAddress.Text = customers[i].Address; txtCity.Text = customers[i].City; txtCounty.Text = customers[i].County; txtState.Text = customers[i].State; txtZIPCode.Text = customers[i].ZIPCode; // Get the gas meter number the user is using striMeterNumber = customers[i].MeterNumber; break; } } // Get a list of all the gas meters that the company is using and check each of them. for (int i = 0; i <= meters.Length - 1; i++) { // If you find a gas meter that corresponds to the customer's account, ... if (meters[i].MeterNumber == striMeterNumber) { // Display a summary of that gas meter txtMeterNumber.Text = meters[i].MeterNumber; txtMeterDetails.Text = string.Format("Meter: {0} {1}", meters[i].Make, meters[i].Model); mcReadingStartDate.SelectionStart = meters[i].MeterReadingDate; txtCounterReadingStart.Text = meters[i].CounterValue.ToString(); break; } } } } }
Control | (Name) | Text | Other Properties |
Label | Customer Account Information | BackColor: Gray |
|
Label | Account #: | ||
TextBox | txtAccountNumber | ||
Label | Customer Name: | ||
TextBox | txtCustomerName | ||
Label | Address | ||
TextBox | txtAddress | ||
TextBox | txtCity | ||
TextBox | txtCounty | ||
TextBox | txtState | ||
TextBox | txtZIPCode | ||
Label | Meter Information | BackColor: Gray |
|
Label | Meter Details: | ||
TextBox | txtMeterNumber | ||
TextBox | txtMeterDetails | ||
Label | Meter Reading | ||
Label | _________________________ | ||
Label | Reading Start Date | ||
Label | Reading End Date | ||
MonthCalendar | mcReadingStartDate | ||
MonthCalendar | mcReadingEndDate | ||
Label | Counter Reading Start: | ||
TextBox | txtCounterReadingStart | TextAlign: Right | |
Label | Counter Reading End: | ||
TextBox | txtCounterReadingEnd | TextAlign: Right | |
Label | Number of Days: | ||
TextBox | txtNumberOfDays | ||
Label | CCF Total: | ||
TextBox | txtCCFTotal | TextAlign: Right | |
Label | Total Therms (CCF * 1.0367): | ||
TextBox | txtTotalTherms | TextAlign: Right | |
Label | Bill Values | BackColor: Gray |
|
Label | Transportation Charges: | ||
TextBox | txtTransportationCharges | TextAlign: Right | |
Label | Delivery Total: | ||
TextBox | txtDeliveryTotal | TextAlign: Right | |
Label | Distrib. Adjust (*0.13086): | ||
TextBox | txtDistributionAdjustment | TextAlign: Right | |
Label | Environmental Charges: | ||
TextBox | txtEnvironmentalCharges | TextAlign: Right | |
Label | First 50 Therms (* 0.5269): | ||
TextBox | txtFirst50Therms | TextAlign: Right | |
Label | Over 50 Therms (* 0.4995): | ||
TextBox | txtOver50Therms | TextAlign: Right | |
Label | Local/County Taxes: | ||
TextBox | txtLocalTaxes | TextAlign: Right | |
Label | State Taxes: | ||
TextBox | txtStateTaxes | TextAlign: Right | |
Label | Total Charges: | ||
TextBox | txtTotalCharges | TextAlign: Right | |
Label | __________________ | ||
Label | Payment Due Date: | ||
TextBox | txtPaymentDueDate | TextAlign: Right | |
Label | Amount Due: | ||
TextBox | txtAmountDue | TextAlign: Right |
using System;
using System.Windows.Forms;
namespace GasUtilityCompany3
{
public partial class Form1 : Form
{
GasMeter[] meters = new GasMeter[7];
Customer[] customers = new Customer[5];
public Form1()
{
InitializeComponent();
}
private void txtAccountNumber_Leave(object sender, EventArgs e)
{
/* This is the list of utility meters used by the company.
* Every device has a unique meter number. */
meters = new GasMeter[]
{
new GasMeter() { MeterNumber = "582741-38", Make = "Sinton International", Model = "D-244", MeterReadingDate = new DateTime(2021, 5, 10), CounterValue = 138 },
new GasMeter() { MeterNumber = "293847-27", Make = "Archimeda", Model = "LP2066", MeterReadingDate = new DateTime(2021, 8, 3), CounterValue = 2866 },
new GasMeter() { MeterNumber = "928731-59", Make = "EnvioSmart", Model = "84-D9703", MeterReadingDate = new DateTime(2020, 12, 8), CounterValue = 8016 },
new GasMeter() { MeterNumber = "520246-85", Make = "Garland Worldwide", Model = "GFH-2260", MeterReadingDate = new DateTime(2021, 5, 22), CounterValue = 22683 },
new GasMeter() { MeterNumber = "797047-27", Make = "Archimeda", Model = "LP2066", MeterReadingDate = new DateTime(2021, 10, 4), CounterValue = 725 },
new GasMeter() { MeterNumber = "425837-14", Make = "EnvioSmart", Model = "28-G4428", MeterReadingDate = new DateTime(2021, 1, 1), CounterValue = 6114 },
new GasMeter() { MeterNumber = "162460-82", Make = "Archimeda", Model = "Di8000", MeterReadingDate = new DateTime(2020, 6, 3), CounterValue = 15502 },
new GasMeter() { MeterNumber = "864085-92", Make = "Sinton International", Model = "D-244", MeterReadingDate = new DateTime(2021, 10, 5), CounterValue = 83 }
};
/* This si the list of customers who use the gas produced and distributed by the company.
* Every customer uses a utility metter number. That number must (1) correspond to a gas
* meter from the above list, (2) the gas meter a customer uses must be unique among the other customers. */
customers = new Customer[]
{
new Customer(){ AccountNumber = "620-9720-824", MeterNumber = "293847-27", FirstName = "Jefferey", LastName = "Parriot", Address = "688 Gorman Str", City = "Rockville", County = "Montgomery", State = "MD", ZIPCode = "20856" },
new Customer(){ AccountNumber = "482-1397-851", MeterNumber = "425837-14", FirstName = "Christopher", LastName = "McGee", Address = "3316 Sanderson Rd", City = "Alexandria", County = "", State = "VA", ZIPCode = "22312" },
new Customer(){ AccountNumber = "852-9360-597", MeterNumber = "582741-38", FirstName = "Sandra", LastName = "Rhodes", Address = "11158 Grattos Ave", City = "Hyattsville", County = "Prince George", State = "MD", ZIPCode = "20783" },
new Customer(){ AccountNumber = "209-5384-805", MeterNumber = "928731-59", FirstName = "Marco", LastName = "Ramos", Address = "9012 Jefferson Crt", City = "Washington", County = "", State = "DC", ZIPCode = "20012" },
new Customer(){ AccountNumber = "972-3848-393", MeterNumber = "797047-27", FirstName = "Gabrielle", LastName = "Bayley", Address = "799 Boomerang Str", City = "Columbia", County = "Howard", State = "MD", ZIPCode = "21042" }
};
// Request the customer's account number from the user
string acntNbr = txtAccountNumber.Text;
// We will need to identify the gas meter that a customer is using.
string striMeterNumber = string.Empty;
// When the user has typed a customer's account number, visit each of the customers accounts.
for (int i = 0; i <= customers.Length - 1; i++)
{
// Find out if there is a customer record that has the accont number the user had entered.
if (customers[i].AccountNumber == acntNbr)
{
// If the user entered a valid customer's account, display the information of that customer
txtCustomerName.Text = string.Format("{0}, {1}", customers[i].LastName, customers[i].FirstName);
txtAddress.Text = customers[i].Address;
txtCity.Text = customers[i].City;
txtCounty.Text = customers[i].County;
txtState.Text = customers[i].State;
txtZIPCode.Text = customers[i].ZIPCode;
mcReadingStartDate.SelectionStart = meters[i].MeterReadingDate;
// Get the gas meter number the user is using
striMeterNumber = customers[i].MeterNumber;
// Since you found the customer record, stop looking
break;
}
}
// Get a list of all the gas meters that the company is using and check each of them.
for (int i = 0; i <= meters.Length - 1; i++)
{
// If you find a gas meter that corresponds to the customer's account, ...
if (meters[i].MeterNumber == striMeterNumber)
{
// Display a summary of that gas meter
txtMeterNumber.Text = meters[i].MeterNumber;
txtMeterDetails.Text = string.Format("Meter: {0} {1}", meters[i].Make, meters[i].Model);
txtCounterReadingStart.Text = meters[i].CounterValue.ToString();
// Since you found the customer's gas meter, stop looking
break;
}
}
}
private void txtCounterReadingEnd_Leave(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtAccountNumber.Text))
{
MessageBox.Show("You must enter the starting value of the counter reading.",
"Quatro Gas Company");
return;
}
if (string.IsNullOrEmpty(txtMeterNumber.Text))
{
MessageBox.Show("You must enter the meter number of the gas meter used by " +
"the customer (normally, this is done by entering the customer's account number).",
"Quatro Gas Company");
return;
}
if (string.IsNullOrEmpty(txtCounterReadingEnd.Text))
{
MessageBox.Show("You must enter the ending value of the counter reading.",
"Quatro Gas Company");
return;
}
int meterReadingStart = int.Parse(txtCounterReadingStart.Text);
int meterReadingEnd = int.Parse(txtCounterReadingEnd.Text);
int consumption = meterReadingEnd - meterReadingStart;
double totalTherms = consumption * 1.0367;
double first50Therms, over50Therms;
if (totalTherms < 50)
{
first50Therms = totalTherms * 0.5269;
over50Therms = 0;
}
else
{
first50Therms = 50 * 0.5269;
over50Therms = (totalTherms - 50) * 0.4995;
}
/* We will use some random values for the transportation charge (my
* research didn't make it clear to me how gas companies set this price. */
Random rndTransportation = new Random();
double[] transportationValues = { 9.75, 9.95, 10.25, 10.45, 10.85, 12.55, 13.50, 14.35 };
double transportationCharges = transportationValues[rndTransportation.Next(1, transportationValues.Length)];
double deliveryTotal = transportationCharges + first50Therms + over50Therms;
double distribution = totalTherms * 0.11086;
double environment = deliveryTotal * 0.0045;
double state = transportationCharges * 0.0225;
double local = transportationCharges * 0.05826;
double totalCharges = transportationCharges + deliveryTotal + distribution + environment + local + state;
double amtDue = totalCharges;
txtStateTaxes.Text = state.ToString("F");
txtLocalTaxes.Text = local.ToString("F");
txtAmountDue.Text = amtDue.ToString("F");
txtCCFTotal.Text = consumption.ToString();
txtTotalTherms.Text = totalTherms.ToString("F");
txtOver50Therms.Text = over50Therms.ToString("F");
txtTotalCharges.Text = totalCharges.ToString("F");
txtFirst50Therms.Text = first50Therms.ToString("F");
txtDeliveryTotal.Text = deliveryTotal.ToString("F");
txtEnvironmentalCharges.Text = environment.ToString("F");
txtDistributionAdjustment.Text = distribution.ToString("F");
txtLatePaymentAmountDue.Text = (amtDue + 8.35).ToString("F");
txtTransportationCharges.Text = transportationCharges.ToString("F");
}
}
}
The Date Changed Event
When a date has been selected, whether by the user (using the mouse or the keyboard) or by you (through code), the control fires a DateChanged event. The DateChanged event is of type DateRangeEventArgs.
The DateRangeEventArgs class is equipped with two properties: Start and End. When the user clicks a date, these two properties hold the date that was clicked. This means that you can use either of these properties to know the date that was clicked. Both the Start and the End properties are of type DateTime.
Practical Learning: Introducing the Calendar Control
The Date Picker
Introduction
Like the calendar, the date picker is a control that allows the user to select a date value:
To support the date-picker, the .NET Framework provides a class named DateTimePicker. You can declare a variable for it and initialize it using the new operator. Here is an example:
using System.Drawing; using System.Windows.Forms; public class Exercise : System.Windows.Forms.Form { DateTimePicker dtpDataHired; public Exercise() { InitializeComponent(); } void InitializeComponent() { dtpDataHired = new DateTimePicker(); dtpDataHired.Location = new Point(12, 12); } }
To visually add a date/time picker to a form or other container, in the Common Controls section of the Toolbox, click DateTimePicker and click the host. The date/time picker control can be considered as two controls in one: you just have to choose which one of both controls you want to use.
After adding the date/time picker control to the form, to allow the user to set the dates and not the times on the control, set its Format property either to Long (the default) or to Short. Here is an example:
using System.Drawing;
using System.Windows.Forms;
public class Exercise : System.Windows.Forms.Form
{
DateTimePicker dtpDataHired;
public Exercise()
{
InitializeComponent();
}
void InitializeComponent()
{
dtpDataHired = new DateTimePicker();
dtpDataHired.Location = new Point(12, 12);
dtpDataHired.Format = DateTimePickerFormat.Long;
}
}
Characteristics of the Date Picker
The Spin Button
After adding a date time picker control and setting its Format to either Long (the default) or Short, the control becomes a combo box (the default). If you do not like the combo box, you can display a spin button instead. This characteristic is controlled by the ShowUpDown Boolean property. When its value is set to False (the default), the control appears as a combo box. It you set it to True, it appears as a spin button:
If the control displays a combo box and if the user clicks the arrow on the Date control, a calendar object similar to the month calendar control displays:
The Check Box
In some cases, you may want to decide when to allow the user to select a date or when to disable it. There are two ways you can do this. You can use the Control's Enabled property that all other controls inherit. Another technique you can use is to display a check box on the left side of the text box section of the control. The presence or absence of the check box is controlled by the ShowCheckBox Boolean property whose default value is False. If you set it to True, a check box appears:
When the check box is checked, the user can change the displayed date. When the check box is unchecked, the control is displayed and the user cannot change the date. The user must first put a check mark in the check box in order to be able to change the date.
The state of the check box is controlled by the Boolean Checked property. If the user clicks the check box to put a check mark in it, this property's value becomes true.
Using the Date Picker
As its name indicates, the date picker either displays a date or it allows the user to specify a date. The control follows the format of the date values specified in the regional settings of Control Panel. Consequently, the date is made of various sections including the name of the day, the name of the month, the numeric day in the month, and the year.
If the control is equipped with a spin button, to change the month, the user can click the month and then click one of the arrow buttons of the spin control. The user can also use the arrow keys to get the same effect. In the same way, the user can change the values of the day or the year.
If the control appears as a combo box, the user can click the arrow button. This would display a calendar:
When the calendar displays, the control fires an event named DropDown. The DropDown event is of type EventArgs. This means that this event does not carry any significant information, other than to let you know that the calendar of the control has been dropped to display.
While the calendar is displaying, the user can change the month, change the year, or click a date to select one. The user can still change the date in the text box side of the control. However it is done, on the text box or on the calendar, when the date of the control has been changed, the control fires an event named ValueChanged. The ValueChanged event, which is the default event of the control, is of type EventArgs, meaning it doesn't give you any detail about the date that was selected or about anything the user did. You would use your own means of finding out what date the user had selected or specified. This can easily be done by getting the Value property of the control.
If the control is displaying a calendar, once the user clicks a date, the calendar disappears and the control becomes a combo box again. When the calendar retracts, the control fires an event named CloseUp. The CloseUp event is of type EventArgs, which means it doesn't carry any particular information other than letting you know that the calendar has been closed.
The Minimum and the Maximum Dates
If you want to control the range of dates the user can select, use the MinDate and the MaxDate properties as we mentioned them from the MonthCalendar control. Here is an example:
using System.Drawing;
using System.Windows.Forms;
public class Exercise : System.Windows.Forms.Form
{
DateTimePicker dtpDataHired;
public Exercise()
{
InitializeComponent();
}
void InitializeComponent()
{
dtpDataHired = new DateTimePicker();
dtpDataHired.Location = new Point(12, 12);
dtpDataHired.MinDate = new DateTime(2000, 1, 1);
}
}
The Value of the Calendar
When you add the date picker control to your form or container, it displays the date of the computer on the day (or night) the control was added. If you want the control to display a different date, set the desired value in the Value field of the Properties window. At any time, you can find out what value the Date Picker has by retrieving the value of the Value property.
The Custom Format of the Calendar
If you set the Format property to Long, the date displays using the Long Date format of Control Panel. If you set the Format to Short, the control uses the Short Date value of Control Panel. If you want to customize the way the date is displayed, set the Format property to Custom. After setting the Format to Custom, use the CustomFormat property to create the desired format. The format is created by combining the following characters:
Format | Used For | Description |
d | Days | Displays the day as a number from 1 to 31 |
dd | Days | Displays the day as a number with a leading 0 if the number is less than 10 |
ddd | Weekdays | Displays a weekday name with 3 letters as Mon, Tue, etc |
dddd | Weekdays | Displays the complete name of a week day as Monday, etc |
M | Months | Displays the numeric month from 1 to 12 |
MM | Months | Displays the numeric month with a leading 0 if the number is less than 10 |
MMM | Months | Displays the short name of the month as Jan, Feb, Mar, etc |
MMMM | Months | Displays the complete name of the month as January, etc |
yy | Years | Displays two digits for the year as 00 for 2000 or 03 for 2003 |
yyyy | Years | Displays the numeric year with 4 digits |
Here is an example:
using System.Drawing;
using System.Windows.Forms;
public class Exercise : System.Windows.Forms.Form
{
DateTimePicker dtpDataHired;
public Exercise()
{
InitializeComponent();
}
void InitializeComponent()
{
dtpDataHired = new DateTimePicker();
dtpDataHired.Location = new Point(12, 12);
dtpDataHired.Format = DateTimePickerFormat.Custom;
dtpDataHired.CustomFormat = "dd MMMM yyyy";
}
}
This means that you should be reluctant to let the users type whatever they want. The less they type, the less checking you need to do.
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 are two examples:
using System; using static System.Console; public class Exercise { public static int Main(string[] args) { Title = "Dates Characteristics"; DateTime date1 = new DateTime(1988, 10, 6); DateTime date2 = new DateTime(1990, 8, 12); WriteLine("{0} was a leap year: {1}", date1.Year, DateTime.IsLeapYear(date1.Year)); WriteLine("{0} was a leap year: {1}", date2.Year, DateTime.IsLeapYear(date2.Year)); WriteLine("================================="); return 8; } }
This would produce:
1988 was a leap year: True 1990 was a leap year: False ================================= Press any key to continue . . .
The Day of the Week
The DateTime structure is equipped with a property that can be used to retrieve the day of the week for a given date. The property is named DayOfWeek. To get the day of the week, access the DayOfWeek property a your DateTime value or variable. The values are stored in the DayOfWeek enumeration. Here is an example:
using System; using static System.Console; public class Exercise { public static int Main(string[] args) { Title = "Dates Characteristics"; DateTime date = new DateTime(1988, 10, 6); WriteLine("Date and Time: {0}", date); WriteLine("Day of the week: {0}", date.DayOfWeek); WriteLine("======================================"); return 10; } }
This would produce:
Date and Time: 10/6/1988 12:00:00 AM Day of the week: Thursday ====================================== Press any key to continue . . .
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:
using System;
using static System.Console;
public class Exercise
{
public static int Main(string[] args)
{
Title = "Dates Characteristics";
DateTime startDate = new DateTime(1988, 10, 6);
// This will be used to add 8 days to the previous date
DateTime endDate = startDate.AddDays(8);
WriteLine("Starting Date: {0}", startDate);
WriteLine("Ending Date: {0}", endDate);
WriteLine("======================================");
return 8;
}
}
This would produce:
Starting Date: 10/6/1988 12:00:00 AM Ending Date: 10/14/1988 12:00:00 AM ====================================== Press any key to continue . . .
If you pass a positive value to the DateTime.AddDays() method, a number of days is added to the DateTime variable.
Practical Learning: Adding Days to a Date Value
using System; using System.Windows.Forms; namespace GasUtilityCompany32 { public partial class Form1 : Form { GasMeter[] meters = new GasMeter[7]; Customer[] customers = new Customer[5]; public Form1() { InitializeComponent(); } private void txtAccountNumber_Leave(object sender, EventArgs e) { . . . // Get a list of all the gas meters that the company is using and check each of them. for (int i = 0; i <= meters.Length - 1; i++) { // If you find a gas meter that corresponds to the customer's account, ... if (meters[i].MeterNumber == striMeterNumber) { // Display a summary of that gas meter txtMeterNumber.Text = meters[i].MeterNumber; txtMeterDetails.Text = string.Format("Meter: {0} {1}", meters[i].Make, meters[i].Model); mcReadingStartDate.SelectionStart = meters[i].MeterReadingDate; mcReadingEndDate.SelectionStart = meters[i].MeterReadingDate.AddDays(30); txtCounterReadingStart.Text = meters[i].CounterValue.ToString(); // Since you found the customer's gas meter, stop looking break; } } } private void txtCounterReadingEnd_Leave(object sender, EventArgs e) { . . . txtStateTaxes.Text = state.ToString("F"); txtLocalTaxes.Text = local.ToString("F"); txtAmountDue.Text = amtDue.ToString("F"); txtCCFTotal.Text = consumption.ToString(); txtTotalTherms.Text = totalTherms.ToString("F"); txtOver50Therms.Text = over50Therms.ToString("F"); txtTotalCharges.Text = totalCharges.ToString("F"); txtFirst50Therms.Text = first50Therms.ToString("F"); txtDeliveryTotal.Text = deliveryTotal.ToString("F"); txtEnvironmentalCharges.Text = environment.ToString("F"); txtDistributionAdjustment.Text = distribution.ToString("F"); txtLatePaymentAmountDue.Text = (amtDue + 8.35).ToString("F"); txtTransportationCharges.Text = transportationCharges.ToString("F"); txtPaymentDueDate.Text = mcReadingEndDate.SelectionStart.AddDays(21).ToShortDateString(); } private void mcReadingEndDate_DateChanged(object sender, DateRangeEventArgs e) { } } }
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:
using System; using static System.Console; public class Exercise { public static int Main(string[] args) { Title = "Dates Characteristics"; DateTime startDate = new DateTime(1988, 10, 6); // This will be used to add 172 days to the previous date TimeSpan ts = new TimeSpan(172, 0, 0, 0); // Pass the TimeSpan object to the date DateTime endDate = startDate.Add(ts); WriteLine("Starting Date: {0}", startDate); WriteLine("Ending Date: {0}", endDate); WriteLine("======================================"); return 10; } }
This would produce:
Starting Date: 10/6/1988 12:00:00 AM Ending Date: 3/27/1989 12:00:00 AM ====================================== Press any key to continue . . .
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.
Practical Learning: Subtracting a Date Value
using System;
using System.Windows.Forms;
namespace GasUtilityCompany32
{
public partial class Form1 : Form
{
GasMeter[] meters = new GasMeter[7];
Customer[] customers = new Customer[5];
public Form1()
{
InitializeComponent();
}
private void txtAccountNumber_Leave(object sender, EventArgs e)
{
. . .
}
private void txtCounterReadingEnd_Leave(object sender, EventArgs e)
{
. . .
}
private void mcReadingEndDate_DateChanged(object sender, DateRangeEventArgs e)
{
DateTime dtStart = mcReadingStartDate.SelectionStart;
DateTime dtEnd = mcReadingEndDate.SelectionStart;
TimeSpan tsDays = dtEnd.Subtract(dtStart);
txtNumberOfDays.Text = tsDays.Days.ToString();
}
}
}
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:
using System;
using static System.Console;
public class Exercise
{
public static int Main(string[] args)
{
Title = "Dates Characteristics";
DateTime startDate = new DateTime(1988, 10, 6);
// This will be used to add 172 days to the previous date
TimeSpan ts = new TimeSpan(-10, 0, 0, 0);
// Pass the TimeSpan object to the date
DateTime endDate = startDate.Add(ts);
// And display it
WriteLine("Starting Date: {0}", startDate);
WriteLine("Ending Date: {0}", endDate);
WriteLine("======================================");
return 11;
}
}
This would produce:
Starting Date: 10/6/1988 12:00:00 AM Ending Date: 9/26/1988 12:00:00 AM ====================================== Press any key to continue . . .
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.
Practical Learning: Adding Months to a Date Value
using System;
using System.Windows.Forms;
namespace GasUtilityCompany32
{
public partial class Form1 : Form
{
GasMeter[] meters = new GasMeter[7];
Customer[] customers = new Customer[5];
public Form1()
{
InitializeComponent();
}
private void txtAccountNumber_Leave(object sender, EventArgs e)
{
/* This is the list of utility meters used by the company.
* Every device has a unique meter number. */
meters = new GasMeter[]
{
new GasMeter() { MeterNumber = "582741-38", Make = "Sinton International", Model = "D-244", MeterReadingDate = new DateTime(2021, 5, 10), CounterValue = 138 },
new GasMeter() { MeterNumber = "293847-27", Make = "Archimeda", Model = "LP2066", MeterReadingDate = new DateTime(2021, 8, 3), CounterValue = 2866 },
new GasMeter() { MeterNumber = "928731-59", Make = "EnvioSmart", Model = "84-D9703", MeterReadingDate = new DateTime(2020, 12, 8), CounterValue = 8016 },
new GasMeter() { MeterNumber = "520246-85", Make = "Garland Worldwide", Model = "GFH-2260", MeterReadingDate = new DateTime(2021, 5, 22), CounterValue = 22683 },
new GasMeter() { MeterNumber = "797047-27", Make = "Archimeda", Model = "LP2066", MeterReadingDate = new DateTime(2021, 10, 4), CounterValue = 725 },
new GasMeter() { MeterNumber = "425837-14", Make = "EnvioSmart", Model = "28-G4428", MeterReadingDate = new DateTime(2021, 1, 1), CounterValue = 6114 },
new GasMeter() { MeterNumber = "162460-82", Make = "Archimeda", Model = "Di8000", MeterReadingDate = new DateTime(2020, 6, 3), CounterValue = 15502 },
new GasMeter() { MeterNumber = "864085-92", Make = "Sinton International", Model = "D-244", MeterReadingDate = new DateTime(2021, 10, 5), CounterValue = 83 }
};
/* This si the list of customers who use the gas produced and distributed by the company.
* Every customer uses a utility metter number. That number must (1) correspond to a gas
* meter from the above list, (2) the gas meter a customer uses must be unique among the other customers. */
customers = new Customer[]
{
new Customer(){ AccountNumber = "620-9720-824", MeterNumber = "293847-27", FirstName = "Jefferey", LastName = "Parriot", Address = "688 Gorman Str", City = "Rockville", County = "Montgomery", State = "MD", ZIPCode = "20856" },
new Customer(){ AccountNumber = "482-1397-851", MeterNumber = "425837-14", FirstName = "Christopher", LastName = "McGee", Address = "3316 Sanderson Rd", City = "Alexandria", County = "", State = "VA", ZIPCode = "22312" },
new Customer(){ AccountNumber = "852-9360-597", MeterNumber = "582741-38", FirstName = "Sandra", LastName = "Rhodes", Address = "11158 Grattos Ave", City = "Hyattsville", County = "Prince George", State = "MD", ZIPCode = "20783" },
new Customer(){ AccountNumber = "209-5384-805", MeterNumber = "928731-59", FirstName = "Marco", LastName = "Ramos", Address = "9012 Jefferson Crt", City = "Washington", County = "", State = "DC", ZIPCode = "20012" },
new Customer(){ AccountNumber = "972-3848-393", MeterNumber = "797047-27", FirstName = "Gabrielle", LastName = "Bayley", Address = "799 Boomerang Str", City = "Columbia", County = "Howard", State = "MD", ZIPCode = "21042" }
};
// Request the customer's account number from the user
string acntNbr = txtAccountNumber.Text;
// We will need to identify the gas meter that a customer is using.
string striMeterNumber = string.Empty;
// When the user has typed a customer's account number, visit each of the customers accounts.
for (int i = 0; i <= customers.Length - 1; i++)
{
// Find out if there is a customer record that has the accont number the user had entered.
if (customers[i].AccountNumber == acntNbr)
{
// If the user entered a valid customer's account, display the information of that customer
txtCustomerName.Text = string.Format("{0}, {1}", customers[i].LastName, customers[i].FirstName);
txtAddress.Text = customers[i].Address;
txtCity.Text = customers[i].City;
txtCounty.Text = customers[i].County;
txtState.Text = customers[i].State;
txtZIPCode.Text = customers[i].ZIPCode;
mcReadingStartDate.SelectionStart = meters[i].MeterReadingDate;
// Get the gas meter number the user is using
striMeterNumber = customers[i].MeterNumber;
// Since you found the customer record, stop looking
break;
}
}
// Get a list of all the gas meters that the company is using and check each of them.
for (int i = 0; i <= meters.Length - 1; i++)
{
// If you find a gas meter that corresponds to the customer's account, ...
if (meters[i].MeterNumber == striMeterNumber)
{
// Display a summary of that gas meter
txtMeterNumber.Text = meters[i].MeterNumber;
txtMeterDetails.Text = string.Format("Meter: {0} {1}", meters[i].Make, meters[i].Model);
mcReadingStartDate.SelectionStart = meters[i].MeterReadingDate;
mcReadingEndDate.SelectionStart = meters[i].MeterReadingDate.AddDays(30);
txtCounterReadingStart.Text = meters[i].CounterValue.ToString();
// Since you found the customer's gas meter, stop looking
break;
}
}
}
private void txtCounterReadingEnd_Leave(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(txtAccountNumber.Text))
{
MessageBox.Show("You must enter the starting value of the counter reading.",
"Quatro Gas Company");
return;
}
if (string.IsNullOrEmpty(txtMeterNumber.Text))
{
MessageBox.Show("You must enter the meter number of the gas meter used by " +
"the customer (normally, this is done by entering the customer's account number).",
"Quatro Gas Company");
return;
}
if (string.IsNullOrEmpty(txtCounterReadingEnd.Text))
{
MessageBox.Show("You must enter the ending value of the counter reading.",
"Quatro Gas Company");
return;
}
int meterReadingStart = int.Parse(txtCounterReadingStart.Text);
int meterReadingEnd = int.Parse(txtCounterReadingEnd.Text);
int consumption = meterReadingEnd - meterReadingStart;
double totalTherms = consumption * 1.0367;
double first50Therms, over50Therms;
if (totalTherms < 50)
{
first50Therms = totalTherms * 0.5269;
over50Therms = 0;
}
else
{
first50Therms = 50 * 0.5269;
over50Therms = (totalTherms - 50) * 0.4995;
}
/* We will use some random values for the transportation charge (my
* research didn't make it clear to me how gas companies set this price. */
Random rndTransportation = new Random();
double[] transportationValues = { 9.75, 9.95, 10.25, 10.45, 10.85, 12.55, 13.50, 14.35 };
double transportationCharges = transportationValues[rndTransportation.Next(1, transportationValues.Length)];
double deliveryTotal = transportationCharges + first50Therms + over50Therms;
double distribution = totalTherms * 0.11086;
double environment = deliveryTotal * 0.0045;
double state = transportationCharges * 0.0225;
double local = transportationCharges * 0.05826;
double totalCharges = transportationCharges + deliveryTotal + distribution + environment + local + state;
double amtDue = totalCharges;
txtStateTaxes.Text = state.ToString("F");
txtLocalTaxes.Text = local.ToString("F");
txtAmountDue.Text = amtDue.ToString("F");
txtCCFTotal.Text = consumption.ToString();
txtTotalTherms.Text = totalTherms.ToString("F");
txtOver50Therms.Text = over50Therms.ToString("F");
txtTotalCharges.Text = totalCharges.ToString("F");
txtFirst50Therms.Text = first50Therms.ToString("F");
txtDeliveryTotal.Text = deliveryTotal.ToString("F");
txtEnvironmentalCharges.Text = environment.ToString("F");
txtDistributionAdjustment.Text = distribution.ToString("F");
txtLatePaymentAmountDue.Text = (amtDue + 8.35).ToString("F");
txtTransportationCharges.Text = transportationCharges.ToString("F");
txtPaymentDueDate.Text = mcReadingEndDate.SelectionStart.AddDays(21).ToShortDateString();
txtLatePaymentDueDate.Text = mcReadingEndDate.SelectionStart.AddMonths(1).ToShortDateString();
}
private void mcReadingEndDate_DateChanged(object sender, DateRangeEventArgs e)
{
DateTime dtStart = mcReadingStartDate.SelectionStart;
DateTime dtEnd = mcReadingEndDate.SelectionStart;
TimeSpan tsDays = dtEnd.Subtract(dtStart);
txtNumberOfDays.Text = tsDays.Days.ToString();
}
}
}
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:
using System;
using static System.Console;
public class Exercise
{
public static int Main(string[] args)
{
Title = "Dates Characteristics";
DateTime startDate = new DateTime(1988, 10, 6);
// This will be used to add 8 days to the previous date
DateTime endDate = startDate.AddDays(8);
WriteLine("Starting Date: {0}", startDate);
WriteLine("Ending Date: {0}", endDate);
WriteLine("-----------------------------------------------------------");
if (startDate < endDate)
WriteLine($"{startDate} occurs before {endDate}");
WriteLine("===========================================================");
return 12;
}
}
This would produce:
Starting Date: 10/6/1988 12:00:00 AM Ending Date: 10/14/1988 12:00:00 AM ----------------------------------------------------------- 10/6/1988 12:00:00 AM occurs before 10/14/1988 12:00:00 AM =========================================================== Press any key to continue . . .
Practical Learning: Ending the Lesson
|
||
Previous | Copyright © 2001-2021, FunctionX | Next |
|