Introduction
This tip describes adding an extension method to DateTime
data-type that accepts a format specifier q
or Q
to return the Quarter
for a DateTime
value. Additionally, there is a provision to specify the month of the first quarter. The usage is demonstrated with NUnit unit-tests.
Background
The C# DateTime
data type doesn't have a pre-defined method or format specifier to get the quarter value for a particular date. One way to build support would be to create an extension method to get the quarter value but it would be nice to have a new format specifier for use with string.Format()
and ToString()
that can return the quarter value similar to other specifiers like day, month, year, etc. Unfortunately, defining a customer formatter will limit the usage with only string.Format()
as ToString()
doesn't seem to support a custom formatter (although it does have an overload just for that). So here an extension method is created that builds support for new specifier q
or Q
and returns the Quarter
value for a DateTime
value. Additionally, there is support for specifying the month of first quarter, for example for an Apr to Mar cycle, the first quarter will be month 4.
Extension Method
An extension method ToStringEx()
is defined on DateTime
. Quarter
value is returned for the specifiers q
; any other specifiers are passed on to the default ToString()
method. Some additional code takes care of the provision to specify the starting quarter month.
public static string ToStringEx(this DateTime input, string format)
{
string dateString = string.Empty;
string firstFormatChar = format.Substring(0, 1);
switch (firstFormatChar)
{
case "q":
case "Q":
string remainingFormatChar = format.Substring(1);
int firstQuarterMonth = 1;
if (remainingFormatChar.Length > 0)
{
firstQuarterMonth = int.Parse(remainingFormatChar);
if (firstQuarterMonth < 1 || firstQuarterMonth > 12)
throw new FormatException
("Expecting number between 1 & 12!");
}
int monthNo = input.Month - firstQuarterMonth + 1;
if (monthNo <= 0)
monthNo += 12;
int quarter = (int)Math.Ceiling(monthNo / 3.0);
dateString = quarter.ToString();
break;
default:
dateString = input.ToString
(format, System.Globalization.CultureInfo.InvariantCulture);
break;
}
return dateString;
}
Using the Code
The extension method ToStringEx()
becomes available on all DateTime
values and when invoked with a format specifier q
or Q
shall return the appropriate quarter value. Demonstrating the usage here with a unit test:
[Test]
public void DatetimeExtensionTest()
{
Assert.AreEqual("1", (new DateTime(2013, 1, 1)).ToStringEx("q"));
Assert.AreEqual("3", (new DateTime(2013, 7, 1)).ToStringEx("q"));
Assert.AreEqual("2", (new DateTime(2013, 1, 1)).ToStringEx("q10"));
Assert.AreEqual("4", (new DateTime(2013, 7, 1)).ToStringEx("q10"));
}
Points of Interest
By default, the q
specifier assumes Jan as the starting of the first quarter, the extension method allows passing a number from 1 to 12 to specify the starting month of first quarter - some calculation shifts the reference to the starting of the first quarter. The attached source code has more unit-tests which test for all dates in the four quarters in a year.
History
- 8th April, 2013: Initial version