"Красивые" даты генератор


У меня это "красивая" дата генератор строку в C# - передать дату и возвращает строку с "5 минут назад" или "2 недели, 3 дня назад" и т. д.

Это немного многословный и боровов 61 линий, и мне интересно, если я пропускаю некоторые интересные функции C# или что-то. Какие (если таковые имеются) является лучшим способом, чтобы очистить этот код? Есть какие-то крутые функции C# я могу использовать здесь?

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) {
        stringy = "Just Now";
    } else if (years >= 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 - hours * 60).ToString() + " minutes";
            } else {
                stringy = ", " + (minutes - hours * 60).ToString() + " minute";
            }
        }
        if (hours >= 2) {
            stringy = hours.ToString() + " hours" + stringy + " ago";
        } else {
            stringy = "1 hour" + stringy + " ago";
        }
    } else if (minutes > 1) {
        stringy = minutes.ToString() + " minutes ago";
    }
    return stringy;
}


2670
6
задан 31 мая 2011 в 04:05 Источник Поделиться
Комментарии
4 ответа


  1. Использовать PascalCase для имени метода

  2. Переведите тепловычислитель в течение многих лет и месяцев ниже будет подробно "более эффективным"

  3. Использовать встроенные возврат уменьшает вложенность

  4. Использовать тернарный оператор (?:) по простой логике, чтобы уменьшить , если/еще беспорядок

  5. Используйте формат переопределение метода toString(строковый формат) , чтобы уменьшить строку concats

  6. Используйте строку.Формат с троичным для уменьшения дублирования

Сокращенный вариант я придумал-это 40 линий, но вы можете судить, если он достаточно четкий.

    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("{0} minutes ago");
}

8
ответ дан 31 мая 2011 в 08:05 Источник Поделиться

Некоторые вещи повторяются:

days - weeks * 7
hours - days * 24
minutes - hours * 60

Они могут и должны быть сделаны в собственных переменных - но то, что вы действительно после, кажется

days % 7
hours % 24
minutes % 60

Вы можете заменить:

double hours = diff.Hours + days * 24;

с

double hours = diff.TotalHours;

Существует также TotalMinutes. Вы можете просто использовать математику.Пол() эти значения, чтобы получить int.

Я вижу, что вы собираетесь на одну точку для этой функции, но я думаю, что читаемость бы улучшилась, если есть проще пути короче:

if (minutes <= 1)         
return "Just Now";

if (years >= 1) {
if (years >= 2) {
return years.ToString() + " years ago";
} else {
return "1 year ago";
}

Правка, чтобы добавить:

Есть неоднократные блок кода, который может быть преобразована в отдельную функцию:

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";
}

Тело извлечено функция будет выглядеть как:

if (smallUnitCount > 0) {
if (smallUnitCount > 1) {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitPluralName);
} else {
stringy = String.Format(", {0} {1}", smallUnitCount.ToString() , smallUnitSingularName);
}
}
if (largeUnitCount >= 2) {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitPluralName, stringy);
} else {
stringy = String.Format("{0} {1}{2} ago", largeUnitCount.ToString, largeUnitSingularName, stringy);
}

4
ответ дан 31 мая 2011 в 07:05 Источник Поделиться

Я бы использовал литья двойной для инт вместо того, чтобы пол в вашем случае. Во-первых, потому что я немного осторожными о равенстве сравнение удваивается В лет >= 1. Я бы написал это так:

int years = (int)(diff.TotalDays/365);

3
ответ дан 31 мая 2011 в 09:05 Источник Поделиться

Вы можете сделать это расширение, так что вы можете сделать

string result = DateTime.Now.GetTimeSpan();

Вот как я это сделал несколько времени назад

  /// <summary>
/// Provide extentions for the DateTime Object.
/// </summary>
public static class DateTimeExtensions
{
/// <summary>
/// Gets the relative time for a datetime.
/// </summary>
/// <param name="dateTime">The datetime to get the relative time.</param>
/// <returns>A relative time in english.</returns>
public static string GetTimeSpan(this DateTime dateTime)
{
TimeSpan diff = DateTime.Now.Subtract(dateTime);

if (diff.TotalMinutes < 1)
{
return string.Format("{0:D2} second{1} ago", diff.Seconds, PluralizeIfNeeded(diff.Seconds));
}

if (diff.TotalHours < 1)
{
return string.Format("{0:D2} minute{1} ago", diff.Minutes, PluralizeIfNeeded(diff.Minutes));
}

if (diff.TotalDays < 1)
{
return string.Format("{0:D2} hour{2} and {1:D2} minute{3} ago", diff.Hours, diff.Minutes, PluralizeIfNeeded(diff.Hours), PluralizeIfNeeded(diff.Minutes));
}

if (diff.TotalDays <= 2)
{
return string.Format(
"{0:D2} day{3}, {1:D2} hour{4} and {2:D2} minute{5} ago",
diff.Days,
diff.Hours,
diff.Minutes,
PluralizeIfNeeded(diff.Days),
PluralizeIfNeeded(diff.Hours),
PluralizeIfNeeded(diff.Minutes));
}

if (diff.TotalDays <= 30)
{
return string.Format("{0:D2} days ago", diff.TotalDays);
}

return string.Format("{0:g}", dateTime);
}

/// <summary>
/// Gets a 's' if value is > 1.
/// </summary>
/// <param name="testValue">The value to test.</param>
/// <returns>An 's' if value is > 1, otherwise an empty string.</returns>
private static string PluralizeIfNeeded(int testValue)
{
return testValue > 1 ? "s" : string.Empty;
}
}

0
ответ дан 1 июня 2011 в 09:06 Источник Поделиться