ZetCode

C# Calendar

last modified October 5, 2026

In this article we learn how to work with calendars and cultures in C#.

A DateTime value represents a date and time independently of a particular calendar. A calendar defines how a date is divided into years, months, and days. The System.Globalization namespace contains the Calendar base class and concrete calendars such as GregorianCalendar, HebrewCalendar, HijriCalendar, JapaneseCalendar, and PersianCalendar.

A CultureInfo combines cultural information with a default calendar and date-time formatting rules. Its OptionalCalendars property lists the calendars supported by the culture, while its DateTimeFormat.Calendar property selects the calendar used for formatting.

C# default calendars

Each culture has a default calendar. The default is commonly a GregorianCalendar, but cultures such as fa-IR use a PersianCalendar by default. The available calendars depend on the runtime and operating system globalization data.

Program.cs
using System.Globalization;

string[] cultureNames = { "en-US", "fa-IR", "he-IL" };

foreach (var cultureName in cultureNames)
{
    var culture = CultureInfo.GetCultureInfo(cultureName);

    Console.WriteLine($"{culture.Name}: {culture.Calendar.GetType().Name}");
    Console.WriteLine($"Optional: {culture.OptionalCalendars.Length}");
}

The example displays each culture's default calendar and the number of optional calendars it supports. GetCultureInfo returns a cached, read-only culture, which is sufficient when we only inspect its properties.

$ dotnet run
en-US: GregorianCalendar
Optional: 1
fa-IR: PersianCalendar
Optional: 3
he-IL: GregorianCalendar
Optional: 3

Formatting with a calendar

Set the calendar on a writable culture's DateTimeFormat object to format a DateTime using that calendar. The underlying DateTime does not change; only its textual representation changes.

Program.cs
using System.Globalization;

var date = new DateTime(2026, 10, 5);
var culture = CultureInfo.GetCultureInfo("fa-IR").Clone() as CultureInfo
    ?? throw new InvalidOperationException();

Console.WriteLine(date.ToString("D", CultureInfo.InvariantCulture));

culture.DateTimeFormat.Calendar = new PersianCalendar();
Console.WriteLine(date.ToString("D", culture));

The culture is cloned because the object returned by GetCultureInfo is read-only. The same date is then formatted once with the invariant Gregorian culture and once with the Persian calendar.

$ dotnet run
Monday, 05 October 2026
1405 مهر 13, دوشنبه

Converting calendar fields

A Calendar can extract fields from a DateTime and can construct a DateTime from fields expressed in that calendar. Use calendar methods when the year, month, and day come from a non-Gregorian calendar; do not pass those fields directly to a Gregorian constructor.

Program.cs
using System.Globalization;

var calendar = new HebrewCalendar();
var date = new DateTime(2026, 10, 5);

int year = calendar.GetYear(date);
int month = calendar.GetMonth(date);
int day = calendar.GetDayOfMonth(date);

Console.WriteLine($"Hebrew fields: {year}/{month}/{day}");
var sameDate = calendar.ToDateTime(year, month, day, 0, 0, 0, 0);
Console.WriteLine(sameDate.ToString("d", CultureInfo.InvariantCulture));

The calendar converts between an absolute DateTime value and calendar-specific fields. ToDateTime validates that the fields form a valid date in the selected calendar.

$ dotnet run
Hebrew fields: 5787/1/24
10/05/2026

Calendar arithmetic

Use AddYears, AddMonths, and related methods when the operation should follow a particular calendar's month and year rules. The methods return a new DateTime; they do not modify the original value.

Program.cs
using System.Globalization;

var calendar = new HebrewCalendar();
var date = new DateTime(2026, 10, 5);
var nextMonth = calendar.AddMonths(date, 1);
var nextYear = calendar.AddYears(date, 1);

Console.WriteLine(date.ToString("d", CultureInfo.InvariantCulture));
Console.WriteLine(nextMonth.ToString("d", CultureInfo.InvariantCulture));
Console.WriteLine(nextYear.ToString("d", CultureInfo.InvariantCulture));

Here the additions use the Hebrew calendar's month and year boundaries while the output is formatted with the invariant Gregorian culture for clarity.

$ dotnet run
10/05/2026
11/04/2026
10/25/2027

Calendar limits

Calendar implementations have different supported ranges. Check MinSupportedDateTime and MaxSupportedDateTime before processing dates supplied by a user, and handle ArgumentOutOfRangeException when a date or calendar field is outside the supported range.

Source

CultureInfo Class - .NET API

Calendar Class - .NET API

In this article we have worked with calendars, cultures, formatting, and calendar arithmetic in C#.

Author

My name is Jan Bodnar, and I am a passionate programmer with extensive programming experience. I have been writing programming articles since 2007. To date, I have authored over 1,400 articles and 8 e-books. I possess more than ten years of experience in teaching programming.

List all C# tutorials.