Aim
To accept a date from the user, decompose it into day, month and year components, and map the identical logic onto a WinForms MonthCalendar control feeding three TextBox fields.
Theory
DateTime is a struct (value type) that packs an entire date-time into a single 64-bit field: 62 bits of ticks (1 tick = 100 nanoseconds elapsed since 0001-01-01) plus 2 bits of DateTimeKind. Properties such as .Day, .Month and .Year are not stored fields — they are computed on demand from the tick count by calendar arithmetic, which is why a DateTime occupies only 8 bytes. Parsing is culture-sensitive: DateTime.TryParse honours the current culture and reports failure through a bool return plus an out parameter instead of throwing — the TryParse pattern is .NET's idiomatic non-throwing validation and is orders of magnitude cheaper than catching FormatException in a loop. When a wire format is fixed by contract, DateTime.TryParseExact with "yyyy-MM-dd" and CultureInfo.InvariantCulture is the deterministic choice. The WinForms half is event-driven programming: MonthCalendar raises DateChanged, whose DateRangeEventArgs e exposes e.Start; the console program prints the exact subscription lambda you would place in a Forms project. A plain console app cannot host controls because it runs no Windows message loop (Application.Run) — which is why this practical ships as a console equivalent plus the wiring recipe.
Requirements
- .NET SDK 8.0+ for the console version (
dotnet new console). - For the GUI variant: Windows with
dotnet new winforms -n DatePicker, or Visual Studio 2022 with the ".NET desktop development" workload.
Procedure
- Create the project:
dotnet new console -n DateParts,cd DateParts, paste the code, rundotnet run. - Enter
2026-07-03(ISO yyyy-MM-dd) and record the four decomposed fields. - Enter nonsense ("hello") and observe the graceful fallback to today's date instead of a crash.
- GUI extension: scaffold
dotnet new winforms, drop aMonthCalendarand threeTextBoxcontrols onto the form, and paste the printed event-handler lambda into the form's constructor.
Explanation of the Code
Console.ReadLine() ?? DateTime.Today.ToString("yyyy-MM-dd")— the null-coalescing operator substitutes today's ISO string when the input stream is closed (returns null).if (!DateTime.TryParse(input, out DateTime date))— C# 7 inlineoutvariable declaration; on failure the program logs a message and assignsDateTime.Today: validation without exceptions.date.Day,date.Month,date.Year— computed properties decoding the tick count;date.ToString("MMMM")applies a format specifier for the full month name (culture-sensitive);date.DayOfWeekreturns a value of theDayOfWeekenum.- The final
Console.WriteLineblock prints the WinForms wiring:monthCalendar.DateChanged += (_, e) => { ... }— a lambda subscribed to the event, with the discard_ignoring the unused sender argument, copyinge.Start.Day/Month/Yearinto the three text boxes.
Expected Output
For input 2026-07-03:
=== Date Selection Demo ===
Enter a date (yyyy-MM-dd): 2026-07-03
Day : 3
Month : 7 (July)
Year : 2026
Day of Week : Friday
WinForms equivalent:
monthCalendar.DateChanged += (_, e) => {
dayBox.Text = e.Start.Day.ToString();
monthBox.Text = e.Start.Month.ToString();
yearBox.Text = e.Start.Year.ToString();
};
🎯 Viva Questions
- Why TryParse instead of Parse? — It signals failure via a
boolinstead of a costlyFormatException; ideal for user input loops. - Is
DateTimea class? — No, a struct (value type) storing 64 bits: tick count plusDateTimeKind. - What is one tick? — 100 nanoseconds, counted from 0001-01-01 00:00.
- What does the
??operator do? — Null-coalescing: yields the left operand unless it is null, otherwise the right. - Which event does
MonthCalendarraise on selection? —DateChanged, carryingDateRangeEventArgswithe.Startande.End. - Why can a console app not show WinForms controls? — It runs no Windows message loop (
Application.Run) and no STA UI thread is configured.