Introduction
I recently had a requirement to output date strings in a format that included the two letter suffix added to the day number. E.g. "January 1st 2008" as opposed to "January 1 2008"
After some investigation, it seems this is not supported out of the box (not surprising really). I concluded that there are a number of ways to implement this behaviour in .NET and decided on a method that is ".NET Framework friendly" and therefore offers good reuse value and is intuitive for .NET developers to use.
Approach
The solution makes use of the custom formatting capabilities in the framework whereby it is possible to implement the IFormatProvider
and ICustomFormatter
interfaces to provide custom string
formatting for use with methods that support formatting such as String.Format()
or Console.WriteLine()
I decided to extend the existing DateTime
format provision in the framework by adding new format options for the DateTime
type. The existing framework support for date formatting is comprehensive; here are a few of the commonly used format specifiers:
Format |
Output |
d |
Short date pattern |
D |
Long date pattern |
F |
Full date/time pattern |
For more, see the MSDN article - Standard DateTime Format Strings.
My idea was to duplicate some of these standard formats (where appropriate) and include the day number suffix. The following date formats have been "extended":
Standard |
Example |
With suffix |
Example |
dd |
31 |
ddx |
31st |
D |
31 January 2008 |
Dx |
31st January 2008 |
F |
31 January 2008 21:30:15 |
Fx |
31st January 2008 21:30:15 |
f |
31 January 2008 21:30 |
fx |
31st January 2008 21:30 |
m |
31 January |
mx |
31st January |
R |
Thu, 31 Jan 2008 21:30:15 GMT |
Rx |
Thu, 31st Jan 2008 21:30:15 GMT |
U |
31 January 2008 21:30:15 |
Ux |
31st January 2008 21:30:15 |
- |
- |
x |
st |
Note, the above examples show dates in English (British) format.
I also wanted to allow a developer to create her or his own date formats by taking advantage of the day number suffix. This makes it possible to use just the suffixed day number to compose your own formats. For example:
string.Format(new DayNumberFormatInfo(),
"It's the {0:ddx} day of the month", DateTime.Now);
Code Structure
There are two projects in the attached solution:
MarkGwilliam.com.Framework.Formatting
- Format class
MarkGwilliam.com.Framework.Formatting.Tests
- Unit tests (requires NUnit)
The DayNumberFormatInfo
class contains the actual formatting logic. This class implements the required framework interface methods which, in turn, call the GetDayNumberSuffix()
helper method to perform the string
formatting.
Demo Project / Unit Tests
This is such a small topic that there isn't really a demo project as such. Instead, there are a number of unit tests which show how to use the supported formats and allow you to tinker with code without inadvertently introducing defects.
Example Usage
In the following example, a format string "Dx
" has been used which is identical to the output you would receive from using a format string of "D
" but with the added two letter suffix to the day number:
string.Format(new GetDayNumberSuffix(), "{0:Dx}", DateTime.Now);
Globalization (And Some Limitations)
The code has been developed to format dates for a British culture. The "extended" date formats all follow British date formatting:
With some extra work, it could be modified to be more culture aware and mimic other cultures but this was outside what I needed so I haven't gone through the trouble. If you're interested in doing so, then you will need to alter the DayNumberFormatInfo.Format()
method and maybe use another technique to replace the day number in the standard formatted string
.
However, this code can still be used effectively in all cultures in its current state and serves as a starting point if you wish to extend it further.
.NET Framework Limitations
I had originally hoped to provide this formatting functionality in calls to DateTime.ToString()
, but the .NET Framework code does NOT support the use of ICustomFormatter
in that way. That is unfortunate as the String.ToString()
function does. This can be proven by looking at the IL code using Reflector or a similar tool. Parsing is also not supported for this reason.
Points of Interest
None really apart from the fact that if you're considering adding some functionality, it's worth checking to see if you can extend the framework in some way. This allows developers to consume your code more easily and hopefully expands your knowledge of .NET along the way.
Further Reading
The topic of customer formatters is well described in the MSDN documentation as well as in the article, Custom String Formatting in .NET, on The Code Project.
History
- Version 1.0 - 16th Nov 2007 - Initial version