DateTime formatting extension method

Notes: I also updated the pieces of code at http://www.extensionmethod.net/Details.aspx?ID=393

In current project, I get some troubles in DateTime class, about format the date time object with the pattern specific string and the current culture, so I decide to code some extension methods in DataTime class in .NET library. And I think it’s it very useful if somebody can use it as right way. I take some idea from this link and coding the enum class for its. After that I also used the Lambda Expression for pass the parameter into the DateTime formatting method. It’s really easy for read code. And below is my implementation for that:


+ DateTimeFormat enum class:

    public enum DateTimeFormat
    {
        [StringValue("unknown")]
        UnknownSpecific = 0,
        [StringValue("d")]
        ShortDate = 1,
        [StringValue("D")]
        LongDate = 2,
        [StringValue("t")]
        ShortTime = 3,
        [StringValue("T")]
        LongTime = 4,
        [StringValue("f")]
        FullShortDateTime = 5,
        [StringValue("F")]
        FullLongDateTime = 6,
        [StringValue("g")]
        GeneralShortDateTime = 7,
        [StringValue("G")]
        GeneralLongDateTime = 8,
        [StringValue("m")]
        MonthDayLowerCase = 9,
        [StringValue("M")]
        MonthDayUpperCase = 10,
        [StringValue("r")]
        Rfc1123LowerCase = 11,
        [StringValue("R")]
        Rfc1123UpperCase = 12,
        [StringValue("s")]
        SortableDateTimeIso8601 = 13,
        [StringValue("U")]
        UniversalSortableDateTime = 14,
        [StringValue("y")]
        YearMonthLowerCase = 15,
        [StringValue("Y")]
        YearMonthUpperCase = 16
    }

+ DateTime extension class:

    public static class DateTimeExtension
    {
        /// <summary>
        /// Toes the string format.
        /// </summary>
        /// <param name="source">The source.</param>
        /// <param name="dateTimeFormat">The date time format.</param>
        /// <returns></returns>
        public static string ToStringFormat(this DateTime source, Expression<Func<DateTimeFormat>> dateTimeFormat)
        {
            var dateTimeFormatCompiled = dateTimeFormat.Compile().Invoke();

            var dateTimeStringFormat = StringEnum.GetStringValue(dateTimeFormatCompiled);

            var currentCulture = Thread.CurrentThread.CurrentCulture;

            return source.ToString(dateTimeStringFormat, currentCulture);
        }
    }

+ Use it:

var shortDateResult = DateTime.Now.ToStringFormat(() => DateTimeFormat.ShortDate);
var fullLongDateTimeResult = DateTime.Now.ToStringFormat(() => DateTimeFormat.FullLongDateTime);
var rfc1123Result = DateTime.Now.ToStringFormat(() => DateTimeFormat.Rfc1123LowerCase);

+ Some unit testing:

    [TestClass]
    public class DateTimeFormatTesting
    {
        [TestMethod]
        public void Can_Get_String_Of_Date_Time_Format()
        {
            var shortDate = StringEnum.GetStringValue(DateTimeFormat.ShortDate);
            Assert.AreEqual(shortDate, "d");
            var longDate = StringEnum.GetStringValue(DateTimeFormat.LongDate);
            Assert.AreEqual(longDate, "D");
            var shortTime = StringEnum.GetStringValue(DateTimeFormat.ShortTime);
            Assert.AreEqual(shortTime, "t");
            var longTime = StringEnum.GetStringValue(DateTimeFormat.LongTime);
            Assert.AreEqual(longTime, "T");
            var monthDayLowerCase = StringEnum.GetStringValue(DateTimeFormat.MonthDayLowerCase);
            Assert.AreEqual(monthDayLowerCase, "m");
            var monthDayUpperCase = StringEnum.GetStringValue(DateTimeFormat.MonthDayUpperCase);
            Assert.AreEqual(monthDayUpperCase, "M");
            var rfc1123UpperCase = StringEnum.GetStringValue(DateTimeFormat.Rfc1123UpperCase);
            Assert.AreEqual(rfc1123UpperCase, "R");

            // and more testing for this enum at here
            // ...
        }
    }
    [TestClass]
    public class DateTimeStringFormatTesting
    {
        private DateTime _originalDateTime;

        [TestInitialize]
        public void InitTestCase()
        {
            _originalDateTime = new DateTime(1984, 3, 11, 2, 30, 58);
        }

        [TestMethod]
        public void Can_Get_Short_Date_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.ShortDate);
            Assert.AreEqual(_originalDateTime.ToShortDateString(), result);
        }

        [TestMethod]
        public void Can_Get_Long_Date_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.LongDate);
            Assert.AreEqual("11 March 1984", result);
        }

        [TestMethod]
        public void Can_Get_Short_Time_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.ShortTime);
            Assert.AreEqual("02:30", result);
        }

        [TestMethod]
        public void Can_Get_Long_Time_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.LongTime);
            Assert.AreEqual("02:30:58", result);
        }

        [TestMethod]
        public void Can_Get_Full_Short_Date_Time_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.FullShortDateTime);
            Assert.AreEqual("11 March 1984 02:30", result);
        }

        [TestMethod]
        public void Can_Get_Full_Long_Date_Time_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.FullLongDateTime);
            Assert.AreEqual("11 March 1984 02:30:58", result);
        }

        [TestMethod]
        public void Can_Get_General_Short_Date_Time_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.GeneralShortDateTime);
            Assert.AreEqual("11/03/1984 02:30", result);
        }

        [TestMethod]
        public void Can_Get_General_Long_Date_Time_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.GeneralLongDateTime);
            Assert.AreEqual("11/03/1984 02:30:58", result);
        }

        [TestMethod]
        public void Can_Get_Month_Day_Lower_Case_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.MonthDayLowerCase);
            Assert.AreEqual("11 March", result);
        }

        [TestMethod]
        public void Can_Get_Month_Day_Upper_Case_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.MonthDayUpperCase);
            Assert.AreEqual("11 March", result);
        }

        [TestMethod]
        public void Can_Get_Rfc1123_Lower_Case_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.Rfc1123LowerCase);
            Assert.AreEqual("Sun, 11 Mar 1984 02:30:58 GMT", result);
        }

        [TestMethod]
        public void Can_Get_Rfc1123_Upper_Case_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.Rfc1123UpperCase);
            Assert.AreEqual("Sun, 11 Mar 1984 02:30:58 GMT", result);
        }

        [TestMethod]
        public void Can_Get_Sortable_DateTime_Iso8601_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.SortableDateTimeIso8601);
            Assert.AreEqual("1984-03-11T02:30:58", result);
        }

        [TestMethod]
        public void Can_Get_Universal_Sortable_DateTime_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.UniversalSortableDateTime);
            Assert.AreEqual("11 March 1984 02:30:58", result);
        }

        [TestMethod]
        public void Can_Get_Year_Month_Lower_Case_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.YearMonthLowerCase);
            Assert.AreEqual("March 1984", result);
        }

        [TestMethod]
        public void Can_Get_Year_Month_Upper_Case_String()
        {
            var result = _originalDateTime.ToStringFormat(() => DateTimeFormat.YearMonthUpperCase);
            Assert.AreEqual("March 1984", result);
        }

        [TestCleanup]
        public void TeardownTestCase()
        {
            if (_originalDateTime != null)
            {
                GC.SuppressFinalize(_originalDateTime);
            }
        }
    }


That is it. Just 2 classes for this extension and if you have some concern about that, don't hesitate to contact with me. Code for this extension is attached in this post as below. Happy coding, mate!

Shout it

14 Comments

  • Why the lambda? Why don't you use the DateTimeFormat parameter in the extension method directly?

  • @Robert: Because I want to wrap my enum object in the Expression Tree, so I can pass it anywhere, even through the wire but do not need to serialize. And one other reason, I want to invert the control out of this extension method, so in the future if have any extend usage, I can do on the Func and pass it into the DateTime extension method. That is my idea. IMHO, your comment is very useful, man. Thanks!

  • I am with Robert. Really weird to use a lambda to pass an enum value. No real advantage for that even after your explanation.

  • method is excellent

  • Excellent post bro worth reading thanks for sharing

  • Your arguments pro-lambda don't make any sense.
    1) Enums are inherently serializable. Expressions are not. SO, you can allready pass a enum anywhere, but you'd have work to do to pass an expression tree.

    2)As for inverting control, I'm not seeing what that buys you:
    // Current method: (passing lambda)
    var formatfunc = () => DateTimeFormat.ShortTime;
    // later
    string strDate = dateTime.ToStringFormat(formatfunc);

    How is that significantly different from:
    // passing enum:
    var formatfunc = () => DateTimeFormat.ShortTime;
    // later
    string strDate = dateTime.ToStringFormat(formatfunc());

    Basically, you've taken a simple, quick function and made it complicated & slow --- remember that Expression.Compile is probably several orders-of-magnatude more involved that the simple text formatting that's the goal of this function.

    Additionally, your method requires StringValueAttribute/StringEnum which are from a third party library that you never mention.

    So, let's see if we can meet the original design goal in a simpler and faster manner. First we need to recognize the dateTime.ToString("string") is the same as dateTime.ToString("String, Thread.CurrentCulture) (look it up in Reflector). Next we need to make a string look like a Enum. That can be done with static properties on a class:

    public static class DateTimeFormat
    {
    public static string UnknownSpecific {get { return "unknown";}}
    public static string ShortDate {get { return "d";}}
    public static string LongDate {get { return "D";}}
    // etc
    }

    So, what with your method is:

    var shortDateResult = DateTime.Now.ToStringFormat(() => DateTimeFormat.ShortDate);

    With mine it's just:

    var shortDateResult = DateTime.Now.ToString(DateTimeFormat.ShortDate);

    No extension method or outside library; just the one static class.

  • Just a note: DateTime is not a class, it's a struct. There's no difference in this particular case, but there are enough differences in general to care about class/struct terminology.

  • You've been kicked..A good thing

  • Greetings from Ohio! I'm bored at work so I decided to check out your website on my iphone during lunch break. I really like the information you provide here and can't wait to take a look when I get home.

    I'm surprised at how fast your blog loaded on my cell phone .. I'm not even using WIFI, just 3G .

    . Anyhow, great blog!

  • Greetings! Very helpful advice in this particular article!
    It is the little changes that make the most important changes.
    Thanks a lot for sharing!

  • If you want to grow your familiarity just keep visiting this site and be
    updated with the most up-to-date news update posted here.

  • This post will help the internet people for setting up new blog or
    even a blog from start to end.

  • Can I simply just say what a comfort to find someone
    that truly understands what they are discussing on the web.
    You actually realize how to bring a problem to light and make it important.

    A lot more people ought to look at this and understand this side of your story.
    I was surprised that you aren't more popular given that you certainly have the gift.

  • Why viewers still make use of to read news papers when in this technological globe all is
    accessible on web?

Comments have been disabled for this content.