Format Specifier to Get Quarter Value of a Date





4.00/5 (1 vote)
Extension method that defines a format specifier q or Q and finds the Quarter for a DateTime value
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!");
}
//shift the reference to the starting of first quarter
int monthNo = input.Month - firstQuarterMonth + 1;
if (monthNo <= 0)
monthNo += 12; //adding 12 when we are crossing the year
//forcing 'double' input and type casting the return value
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()
{
//default case when Jan is the month of first quarter
//Jan is the first quarter by default
Assert.AreEqual("1", (new DateTime(2013, 1, 1)).ToStringEx("q"));
//Jul is expected in 3rd quarter
Assert.AreEqual("3", (new DateTime(2013, 7, 1)).ToStringEx("q"));
//Considering Oct as the start of first quarter
//Jan is the 2nd quarter
Assert.AreEqual("2", (new DateTime(2013, 1, 1)).ToStringEx("q10"));
//Jul is the 4th quarter
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