Рассчитать относительное время в C # - PullRequest
1428 голосов
/ 01 августа 2008

Учитывая конкретное значение DateTime, как отобразить относительное время, например:

  • 2 часа назад
  • 3 дня назад
  • месяц назад

Ответы [ 37 ]

4 голосов
/ 13 сентября 2012

Я бы предоставил несколько удобных методов расширения для этого и сделал бы код более читабельным. Во-первых, пара методов расширения для Int32.

public static class TimeSpanExtensions {

    public static TimeSpan Days(this int value) {

        return new TimeSpan(value, 0, 0, 0);
    }

    public static TimeSpan Hours(this int value) {

        return new TimeSpan(0, value, 0, 0);
    }

    public static TimeSpan Minutes(this int value) {

        return new TimeSpan(0, 0, value, 0);
    }

    public static TimeSpan Seconds(this int value) {

        return new TimeSpan(0, 0, 0, value);
    }

    public static TimeSpan Milliseconds(this int value) {

        return new TimeSpan(0, 0, 0, 0, value);
    }

    public static DateTime Ago(this TimeSpan value) {

        return DateTime.Now - value;
    }
}

Затем один для DateTime.

public static class DateTimeExtensions {

    public static DateTime Ago(this DateTime dateTime, TimeSpan delta) {

        return dateTime - delta;
    }
}

Теперь вы можете сделать что-то вроде ниже:

var date = DateTime.Now;
date.Ago(2.Days()); // 2 days ago
date.Ago(7.Hours()); // 7 hours ago
date.Ago(567.Milliseconds()); // 567 milliseconds ago
4 голосов
/ 06 августа 2013
public string getRelativeDateTime(DateTime date)
{
    TimeSpan ts = DateTime.Now - date;
    if (ts.TotalMinutes < 1)//seconds ago
        return "just now";
    if (ts.TotalHours < 1)//min ago
        return (int)ts.TotalMinutes == 1 ? "1 Minute ago" : (int)ts.TotalMinutes + " Minutes ago";
    if (ts.TotalDays < 1)//hours ago
        return (int)ts.TotalHours == 1 ? "1 Hour ago" : (int)ts.TotalHours + " Hours ago";
    if (ts.TotalDays < 7)//days ago
        return (int)ts.TotalDays == 1 ? "1 Day ago" : (int)ts.TotalDays + " Days ago";
    if (ts.TotalDays < 30.4368)//weeks ago
        return (int)(ts.TotalDays / 7) == 1 ? "1 Week ago" : (int)(ts.TotalDays / 7) + " Weeks ago";
    if (ts.TotalDays < 365.242)//months ago
        return (int)(ts.TotalDays / 30.4368) == 1 ? "1 Month ago" : (int)(ts.TotalDays / 30.4368) + " Months ago";
    //years ago
    return (int)(ts.TotalDays / 365.242) == 1 ? "1 Year ago" : (int)(ts.TotalDays / 365.242) + " Years ago";
}

Значения конверсии дней в месяце и году были взяты из Google.

2 голосов
/ 25 августа 2008

Несомненно, простым способом избавиться от проблемы «1 час назад» было бы увеличение окна, для которого «час назад» действительно. Изменение

if (delta < 5400) // 90 * 60
{
    return "an hour ago";
}

в

if (delta < 7200) // 120 * 60
{
    return "an hour ago";
}

Это означает, что то, что произошло 110 минут назад, будет читаться как «час назад» - это может быть не идеально, но я бы сказал, что это лучше, чем текущая ситуация «1 час назад».

1 голос
/ 04 сентября 2017

Это моя функция, работает как шарм:)

public static string RelativeDate(DateTime theDate)
        {
            var span = DateTime.Now - theDate;
            if (span.Days > 365)
            {
                var years = (span.Days / 365);
                if (span.Days % 365 != 0)
                    years += 1;
                return $"about {years} {(years == 1 ? "year" : "years")} ago";
            }
            if (span.Days > 30)
            {
                var months = (span.Days / 30);
                if (span.Days % 31 != 0)
                    months += 1;
                return $"about {months} {(months == 1 ? "month" : "months")} ago";
            }
            if (span.Days > 0)
                return $"about {span.Days} {(span.Days == 1 ? "day" : "days")} ago";
            if (span.Hours > 0)
                return $"about {span.Hours} {(span.Hours == 1 ? "hour" : "hours")} ago";
            if (span.Minutes > 0)
                return $"about {span.Minutes} {(span.Minutes == 1 ? "minute" : "minutes")} ago";
            if (span.Seconds > 5)
                return $"about {span.Seconds} seconds ago";

            return span.Seconds <= 5 ? "about 5 seconds ago" : string.Empty;
        }
0 голосов
/ 26 мая 2019
// Calculate total days in current year
int daysInYear;

for (var i = 1; i <= 12; i++)
    daysInYear += DateTime.DaysInMonth(DateTime.Now.Year, i);

// Past date
DateTime dateToCompare = DateTime.Now.Subtract(TimeSpan.FromMinutes(582));

// Calculate difference between current date and past date
double diff = (DateTime.Now - dateToCompare).TotalMilliseconds;

TimeSpan ts = TimeSpan.FromMilliseconds(diff);

var years = ts.TotalDays / daysInYear; // Years
var months = ts.TotalDays / (daysInYear / (double)12); // Months
var weeks = ts.TotalDays / 7; // Weeks
var days = ts.TotalDays; // Days
var hours = ts.TotalHours; // Hours
var minutes = ts.TotalMinutes; // Minutes
var seconds = ts.TotalSeconds; // Seconds

if (years >= 1)
    Console.WriteLine(Math.Round(years, 0) + " year(s) ago");
else if (months >= 1)
    Console.WriteLine(Math.Round(months, 0) + " month(s) ago");
else if (weeks >= 1)
    Console.WriteLine(Math.Round(weeks, 0) + " week(s) ago");
else if (days >= 1)
    Console.WriteLine(Math.Round(days, 0) + " days(s) ago");
else if (hours >= 1)
    Console.WriteLine(Math.Round(hours, 0) + " hour(s) ago");
else if (minutes >= 1)
    Console.WriteLine(Math.Round(minutes, 0) + " minute(s) ago");
else if (seconds >= 1)
    Console.WriteLine(Math.Round(seconds, 0) + " second(s) ago");

Console.ReadLine();
0 голосов
/ 03 января 2019

Турецкий локализованная версия ответа Vincents.

    const int SECOND = 1;
    const int MINUTE = 60 * SECOND;
    const int HOUR = 60 * MINUTE;
    const int DAY = 24 * HOUR;
    const int MONTH = 30 * DAY;

    var ts = new TimeSpan(DateTime.UtcNow.Ticks - yourDate.Ticks);
    double delta = Math.Abs(ts.TotalSeconds);

    if (delta < 1 * MINUTE)
        return ts.Seconds + " saniye önce";

    if (delta < 45 * MINUTE)
        return ts.Minutes + " dakika önce";

    if (delta < 24 * HOUR)
        return ts.Hours + " saat önce";

    if (delta < 48 * HOUR)
        return "dün";

    if (delta < 30 * DAY)
        return ts.Days + " gün önce";

    if (delta < 12 * MONTH)
    {
        int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
        return months + " ay önce";
    }
    else
    {
        int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
        return years + " yıl önce";
    }
0 голосов
/ 15 марта 2018

Мой путь намного проще. Вы можете настроить строки возврата так, как хотите

    public static string TimeLeft(DateTime utcDate)
    {
        TimeSpan timeLeft = DateTime.UtcNow - utcDate;
        string timeLeftString = "";
        if (timeLeft.Days > 0)
        {
            timeLeftString += timeLeft.Days == 1 ? timeLeft.Days + " day" : timeLeft.Days + " days";
        }
        else if (timeLeft.Hours > 0)
        {
            timeLeftString += timeLeft.Hours == 1 ? timeLeft.Hours + " hour" : timeLeft.Hours + " hours";
        }
        else
        {
            timeLeftString += timeLeft.Minutes == 1 ? timeLeft.Minutes+" minute" : timeLeft.Minutes + " minutes";
        }
        return timeLeftString;
    }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...