Есть ли более умный способ генерировать «время с» с объектами DateTime - PullRequest
7 голосов
/ 01 августа 2010

У меня есть этот код, чтобы занять время в прошлом и сгенерировать читаемую строку, чтобы представить, как давно это было.

  1. Я бы подумал, что Timespan. Часы дадут вам часыдаже если его несколько дней в прошлом, но похоже, что он разбивает его на отдельные компоненты (дни, месяцы и т. д.).Как бы я получил общее количество часов назад (даже если это более 1 дня?

  2. Есть ли какой-нибудь более понятный способ написания кода такого типа ниже, поскольку он выглядит довольно спагетти-иш.

Вот код

        DateTime when = GetDateTimeinPast();
        TimeSpan ts = DateTime.Now.Subtract(when);

        switch (ts.Days)
        {
            case 0:
               if (ts.Hours < 1)
                    b.Append( ts.Minutes + " minutes ago");
               else
                   b.Append( ts.Hours + " hours ago");
                break;
            case 1:
                b.Append( " yesterday");
                break;
            case 2:
            case 3:                
            case 4:

                b.Append( "on " + when.DayOfWeek.ToString());
                break;
            default:
                b.Append(ts.Days + " days ago");
                break;
        }

Ответы [ 5 ]

15 голосов
/ 01 августа 2010

Используйте свойство TotalHours или другие свойства Total[TimeUnit] в объекте временного диапазона.

Для временного диапазона 1:10 (чч: мм) оно равно 1 Hours и 10 * 1006.* или 1.167 TotalHours и 70 TotalMinutes.

Что касается очистки, используйте ветки if / else, как вы делали ранее.Переключатель / регистр не поможет вам с этими условиями, только для конкретных значений.Как то так:

DateTime when = GetDateTimeinPast();
TimeSpan ts = DateTime.Now.Subtract(when);
if (ts.TotalHours < 1)
    b.AppendFormat("{0} minutes ago", (int)ts.TotalMinutes);
else if (ts.TotalDays < 1)
    b.AppendFormat("{0} hours ago", (int)ts.TotalHours);
//etc...
2 голосов
/ 28 мая 2017

Очень поздний ответ, но я почувствовал необходимость в этом, и поиск общих терминов JS, таких как "C # momentjs datetime" или "C # timeago", показал результаты, которые совсем не помогли - я не хочу поддерживать дополнительный код с жестко закодированными магическими числами, который не будет удобен для локализации. Итак, наконец, в одном из комментариев в другом ответе SO я нашел библиотеку:

Humanizer для .NET - https://github.com/Humanizr/Humanizer#humanize-datetime

Использование:

DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"

И это тоже локализуемо!

1 голос
/ 02 августа 2010

В качестве альтернативы у меня есть решение, которое делает это за пределами дней с неделями, месяцами и годами.Этот подход немного отличается. Он переходит от прошлого к будущему, сначала пробуя большие шаги, и если он сбрасывает переключение на следующий, меньший.

0 голосов
/ 22 марта 2018

Если вам нужна большая гибкость и более умный результат, то есть метод расширения для этого в Olive framework с именем ToTimeDifferenceString () .

Itимеет параметр с именем PrecisionParts.Например:

myDate.ToTimeDifferenceString(1)

, который возвращает «2 дня назад»

или

myDate.ToTimeDifferenceString(2)

, который возвращает «2 дня и 4 часа назад»

0 голосов
/ 12 ноября 2015

Я знаю, что это старый пост, но я нашел это решение, используя рекурсию, после поиска этой темы и прочтения ответа Джеффа Меркадо

private string PeriodOfTimeOutput(TimeSpan tspan, int level = 0)
{
    string how_long_ago = "ago";
    if (level >= 2) return how_long_ago;
    if (tspan.Days > 1)
        how_long_ago = string.Format("{0} Days ago", tspan.Days);
    else if (tspan.Days == 1)
        how_long_ago = string.Format("1 Day {0}", PeriodOfTimeOutput(new TimeSpan(tspan.Hours, tspan.Minutes, tspan.Seconds), level + 1));
    else if (tspan.Hours >= 1)
        how_long_ago = string.Format("{0} {1} {2}", tspan.Hours, (tspan.Hours > 1) ? "Hours" : "Hour", PeriodOfTimeOutput(new TimeSpan(0, tspan.Minutes, tspan.Seconds), level + 1));
    else if (tspan.Minutes >= 1)
        how_long_ago = string.Format("{0} {1} {2}", tspan.Minutes, (tspan.Minutes > 1) ? "Minutes" : "Minute", PeriodOfTimeOutput(new TimeSpan(0, 0, tspan.Seconds), level + 1));
    else if (tspan.Seconds >= 1)
        how_long_ago = string.Format("{0} {1} ago", tspan.Seconds, (tspan.Seconds > 1) ? "Seconds" : "Second");        
    return how_long_ago;
}

, используемого как таковое

var tspan = DateTime.Now.Subtract(reqDate);
string how_long_ago = PeriodOfTimeOutput(tspan);
...