HiveBrain v1.2.0
Get Started
← Back to all entries
patterncsharpModerate

"Pretty" date generator

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
prettydategenerator

Problem

I have this "pretty" date string generator in C# - pass it a date and it returns a string with "5 minutes ago" or "2 weeks, 3 days ago", etc.

It's a little verbose and hogs 61 lines, and I'm wondering if I'm missing out on some nice C# features or something. What (if any) is the best way to clean up this code? Are there any cool c# features I can use here?

```
public static string getTimeSpan(DateTime postDate)
{
string stringy = "";
TimeSpan diff = DateTime.Now.Subtract(postDate);
double years = Math.Floor(diff.TotalDays / 365);
double weeks = Math.Floor(diff.TotalDays / 7);
double days = diff.Days;
double hours = diff.Hours + days * 24;
double minutes = diff.Minutes + hours * 60;
if (minutes = 1) {
if (years >= 2) {
stringy = years.ToString() + " years ago";
} else {
stringy = "1 year ago";
}
} else if (weeks >= 1) {
if ((days - weeks * 7) > 0) {
if ((days - weeks * 7) > 1) {
stringy = ", " + (days - weeks * 7).ToString() + " days";
} else {
stringy = ", " + (days - weeks * 7).ToString() + " day";
}
}
if (weeks >= 2) {
stringy = weeks.ToString() + " weeks" + stringy + " ago";
} else {
stringy = "1 week" + stringy + " ago";
}
} else if (days >= 1) {
if ((hours - days * 24) > 0) {
if ((hours - days * 24) > 1) {
stringy = ", " + (hours - days * 24).ToString() + " hours";
} else {
stringy = ", " + (hours - days * 24).ToString() + " hour";
}
}
if (days >= 2) {
stringy = days.ToString() + " days" + stringy + " ago";
} else {
stringy = "1 day" + stringy + " ago";
}
} else if (hours >= 1) {
if ((minutes - hours * 60) > 0) {
if ((minutes - hours * 60) > 1) {
stringy = ", " + (minutes -

Solution


  • Use PascalCase for the method name



  • Move the calc for years and months lower to be minutely "more efficient"



  • Use inline return to reduces nesting



  • Use ternary operator (?:) for simple logic to reduce if/else clutter



  • Use the format override of ToString(string format) to reduce string concats



  • Use string.Format with a ternary to reduce duplication



The shorter version I came up with is 40 lines, but you can judge if it readable enough.

public static string GetTimeSpan(DateTime postDate) {
        string stringy = string.Empty;
        TimeSpan diff = DateTime.Now.Subtract(postDate);
        double days = diff.Days;
        double hours = diff.Hours + days*24;
        double minutes = diff.Minutes + hours*60;
        if (minutes = 1) {
            return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
        }
        double weeks = Math.Floor(diff.TotalDays/7);
        if (weeks >= 1) {
            double partOfWeek = days - weeks*7;
            if (partOfWeek > 0) {
                stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
            }
            return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
        }
        if (days >= 1) {
            double partOfDay = hours - days*24;
            if (partOfDay > 0) {
                stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
            }
            return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
        }
        if (hours >= 1) {
            double partOfHour = minutes - hours*60;
            if (partOfHour > 0) {
                stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
            }
            return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
        }

        // Only condition left is minutes > 1
        return minutes.ToString("# minutes ago");
    }

Code Snippets

public static string GetTimeSpan(DateTime postDate) {
        string stringy = string.Empty;
        TimeSpan diff = DateTime.Now.Subtract(postDate);
        double days = diff.Days;
        double hours = diff.Hours + days*24;
        double minutes = diff.Minutes + hours*60;
        if (minutes <= 1) {
            return "Just Now";
        }
        double years = Math.Floor(diff.TotalDays/365);
        if (years >= 1) {
            return string.Format("{0} year{1} ago", years, years >= 2 ? "s" : null);
        }
        double weeks = Math.Floor(diff.TotalDays/7);
        if (weeks >= 1) {
            double partOfWeek = days - weeks*7;
            if (partOfWeek > 0) {
                stringy = string.Format(", {0} day{1}", partOfWeek, partOfWeek > 1 ? "s" : null);
            }
            return string.Format("{0} week{1}{2} ago", weeks, weeks >= 2 ? "s" : null, stringy);
        }
        if (days >= 1) {
            double partOfDay = hours - days*24;
            if (partOfDay > 0) {
                stringy = string.Format(", {0} hour{1}", partOfDay, partOfDay > 1 ? "s" : null);
            }
            return string.Format("{0} day{1}{2} ago", days, days >= 2 ? "s" : null, stringy);
        }
        if (hours >= 1) {
            double partOfHour = minutes - hours*60;
            if (partOfHour > 0) {
                stringy = string.Format(", {0} minute{1}", partOfHour, partOfHour > 1 ? "s" : null);
            }
            return string.Format("{0} hour{1}{2} ago", hours, hours >= 2 ? "s" : null, stringy);
        }

        // Only condition left is minutes > 1
        return minutes.ToString("# minutes ago");
    }

Context

StackExchange Code Review Q#2738, answer score: 11

Revisions (0)

No revisions yet.