给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
当前回答
这是我的功能,就像一个魅力:)
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;
}
其他回答
Nuget上还有一个名为Humanizr的软件包,它实际上运行得很好,并且在.NET Foundation中。
DateTime.UtcNow.AddHours(-30).Humanize() => "yesterday"
DateTime.UtcNow.AddHours(-2).Humanize() => "2 hours ago"
DateTime.UtcNow.AddHours(30).Humanize() => "tomorrow"
DateTime.UtcNow.AddHours(2).Humanize() => "2 hours from now"
TimeSpan.FromMilliseconds(1299630020).Humanize() => "2 weeks"
TimeSpan.FromMilliseconds(1299630020).Humanize(3) => "2 weeks, 1 day, 1 hour"
Scott Hanselman在他的博客上写了一篇文章
public static string ToRelativeDate(DateTime input)
{
TimeSpan oSpan = DateTime.Now.Subtract(input);
double TotalMinutes = oSpan.TotalMinutes;
string Suffix = " ago";
if (TotalMinutes < 0.0)
{
TotalMinutes = Math.Abs(TotalMinutes);
Suffix = " from now";
}
var aValue = new SortedList<double, Func<string>>();
aValue.Add(0.75, () => "less than a minute");
aValue.Add(1.5, () => "about a minute");
aValue.Add(45, () => string.Format("{0} minutes", Math.Round(TotalMinutes)));
aValue.Add(90, () => "about an hour");
aValue.Add(1440, () => string.Format("about {0} hours", Math.Round(Math.Abs(oSpan.TotalHours)))); // 60 * 24
aValue.Add(2880, () => "a day"); // 60 * 48
aValue.Add(43200, () => string.Format("{0} days", Math.Floor(Math.Abs(oSpan.TotalDays)))); // 60 * 24 * 30
aValue.Add(86400, () => "about a month"); // 60 * 24 * 60
aValue.Add(525600, () => string.Format("{0} months", Math.Floor(Math.Abs(oSpan.TotalDays / 30)))); // 60 * 24 * 365
aValue.Add(1051200, () => "about a year"); // 60 * 24 * 365 * 2
aValue.Add(double.MaxValue, () => string.Format("{0} years", Math.Floor(Math.Abs(oSpan.TotalDays / 365))));
return aValue.First(n => TotalMinutes < n.Key).Value.Invoke() + Suffix;
}
http://refactormycode.com/codes/493-twitter-esque-relative-dates
C#6版本:
static readonly SortedList<double, Func<TimeSpan, string>> offsets =
new SortedList<double, Func<TimeSpan, string>>
{
{ 0.75, _ => "less than a minute"},
{ 1.5, _ => "about a minute"},
{ 45, x => $"{x.TotalMinutes:F0} minutes"},
{ 90, x => "about an hour"},
{ 1440, x => $"about {x.TotalHours:F0} hours"},
{ 2880, x => "a day"},
{ 43200, x => $"{x.TotalDays:F0} days"},
{ 86400, x => "about a month"},
{ 525600, x => $"{x.TotalDays / 30:F0} months"},
{ 1051200, x => "about a year"},
{ double.MaxValue, x => $"{x.TotalDays / 365:F0} years"}
};
public static string ToRelativeDate(this DateTime input)
{
TimeSpan x = DateTime.Now - input;
string Suffix = x.TotalMinutes > 0 ? " ago" : " from now";
x = new TimeSpan(Math.Abs(x.Ticks));
return offsets.First(n => x.TotalMinutes < n.Key).Value(x) + Suffix;
}
文斯回答的土耳其语本地化版本。
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";
}
这是我的功能,就像一个魅力:)
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;
}
using System;
using System.Collections.Generic;
using System.Linq;
public static class RelativeDateHelper
{
private static Dictionary<double, Func<double, string>> sm_Dict = null;
private static Dictionary<double, Func<double, string>> DictionarySetup()
{
var dict = new Dictionary<double, Func<double, string>>();
dict.Add(0.75, (mins) => "less than a minute");
dict.Add(1.5, (mins) => "about a minute");
dict.Add(45, (mins) => string.Format("{0} minutes", Math.Round(mins)));
dict.Add(90, (mins) => "about an hour");
dict.Add(1440, (mins) => string.Format("about {0} hours", Math.Round(Math.Abs(mins / 60)))); // 60 * 24
dict.Add(2880, (mins) => "a day"); // 60 * 48
dict.Add(43200, (mins) => string.Format("{0} days", Math.Floor(Math.Abs(mins / 1440)))); // 60 * 24 * 30
dict.Add(86400, (mins) => "about a month"); // 60 * 24 * 60
dict.Add(525600, (mins) => string.Format("{0} months", Math.Floor(Math.Abs(mins / 43200)))); // 60 * 24 * 365
dict.Add(1051200, (mins) => "about a year"); // 60 * 24 * 365 * 2
dict.Add(double.MaxValue, (mins) => string.Format("{0} years", Math.Floor(Math.Abs(mins / 525600))));
return dict;
}
public static string ToRelativeDate(this DateTime input)
{
TimeSpan oSpan = DateTime.Now.Subtract(input);
double TotalMinutes = oSpan.TotalMinutes;
string Suffix = " ago";
if (TotalMinutes < 0.0)
{
TotalMinutes = Math.Abs(TotalMinutes);
Suffix = " from now";
}
if (null == sm_Dict)
sm_Dict = DictionarySetup();
return sm_Dict.First(n => TotalMinutes < n.Key).Value.Invoke(TotalMinutes) + Suffix;
}
}
与此问题的另一个答案相同,但作为静态字典的扩展方法。