给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
当前回答
文斯回答的土耳其语本地化版本。
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";
}
其他回答
// 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();
我想我应该用类和多态性来尝试一下。我以前的迭代使用了子类,结果开销太大。我已经切换到一个更灵活的委托/公共属性对象模型,这明显更好。我的代码稍微准确一点,我希望我能想出一种更好的方法来生成“几个月前”的代码,而这种方法看起来并没有过度设计。
我想我还是会坚持Jeff的if-then-cascade,因为它的代码更少,而且更简单(肯定更容易确保它按预期工作)。
对于以下代码,PrintRelativeTime.GetRelativeTime message(TimeSpan ago)返回相对时间消息(例如“昨天”)。
public class RelativeTimeRange : IComparable
{
public TimeSpan UpperBound { get; set; }
public delegate string RelativeTimeTextDelegate(TimeSpan timeDelta);
public RelativeTimeTextDelegate MessageCreator { get; set; }
public int CompareTo(object obj)
{
if (!(obj is RelativeTimeRange))
{
return 1;
}
// note that this sorts in reverse order to the way you'd expect,
// this saves having to reverse a list later
return (obj as RelativeTimeRange).UpperBound.CompareTo(UpperBound);
}
}
public class PrintRelativeTime
{
private static List<RelativeTimeRange> timeRanges;
static PrintRelativeTime()
{
timeRanges = new List<RelativeTimeRange>{
new RelativeTimeRange
{
UpperBound = TimeSpan.FromSeconds(1),
MessageCreator = (delta) =>
{ return "one second ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.FromSeconds(60),
MessageCreator = (delta) =>
{ return delta.Seconds + " seconds ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.FromMinutes(2),
MessageCreator = (delta) =>
{ return "one minute ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.FromMinutes(60),
MessageCreator = (delta) =>
{ return delta.Minutes + " minutes ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.FromHours(2),
MessageCreator = (delta) =>
{ return "one hour ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.FromHours(24),
MessageCreator = (delta) =>
{ return delta.Hours + " hours ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.FromDays(2),
MessageCreator = (delta) =>
{ return "yesterday"; }
},
new RelativeTimeRange
{
UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-1)),
MessageCreator = (delta) =>
{ return delta.Days + " days ago"; }
},
new RelativeTimeRange
{
UpperBound = DateTime.Now.Subtract(DateTime.Now.AddMonths(-2)),
MessageCreator = (delta) =>
{ return "one month ago"; }
},
new RelativeTimeRange
{
UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-1)),
MessageCreator = (delta) =>
{ return (int)Math.Floor(delta.TotalDays / 30) + " months ago"; }
},
new RelativeTimeRange
{
UpperBound = DateTime.Now.Subtract(DateTime.Now.AddYears(-2)),
MessageCreator = (delta) =>
{ return "one year ago"; }
},
new RelativeTimeRange
{
UpperBound = TimeSpan.MaxValue,
MessageCreator = (delta) =>
{ return (int)Math.Floor(delta.TotalDays / 365.24D) + " years ago"; }
}
};
timeRanges.Sort();
}
public static string GetRelativeTimeMessage(TimeSpan ago)
{
RelativeTimeRange postRelativeDateRange = timeRanges[0];
foreach (var timeRange in timeRanges)
{
if (ago.CompareTo(timeRange.UpperBound) <= 0)
{
postRelativeDateRange = timeRange;
}
}
return postRelativeDateRange.MessageCreator(ago);
}
}
聚会晚了几年,但我有一个要求,无论是过去还是将来的约会,都要这样做,所以我把杰夫和文森特的约会结合在一起。这是一场盛大的盛会!:)
public static class DateTimeHelper
{
private const int SECOND = 1;
private const int MINUTE = 60 * SECOND;
private const int HOUR = 60 * MINUTE;
private const int DAY = 24 * HOUR;
private const int MONTH = 30 * DAY;
/// <summary>
/// Returns a friendly version of the provided DateTime, relative to now. E.g.: "2 days ago", or "in 6 months".
/// </summary>
/// <param name="dateTime">The DateTime to compare to Now</param>
/// <returns>A friendly string</returns>
public static string GetFriendlyRelativeTime(DateTime dateTime)
{
if (DateTime.UtcNow.Ticks == dateTime.Ticks)
{
return "Right now!";
}
bool isFuture = (DateTime.UtcNow.Ticks < dateTime.Ticks);
var ts = DateTime.UtcNow.Ticks < dateTime.Ticks ? new TimeSpan(dateTime.Ticks - DateTime.UtcNow.Ticks) : new TimeSpan(DateTime.UtcNow.Ticks - dateTime.Ticks);
double delta = ts.TotalSeconds;
if (delta < 1 * MINUTE)
{
return isFuture ? "in " + (ts.Seconds == 1 ? "one second" : ts.Seconds + " seconds") : ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 2 * MINUTE)
{
return isFuture ? "in a minute" : "a minute ago";
}
if (delta < 45 * MINUTE)
{
return isFuture ? "in " + ts.Minutes + " minutes" : ts.Minutes + " minutes ago";
}
if (delta < 90 * MINUTE)
{
return isFuture ? "in an hour" : "an hour ago";
}
if (delta < 24 * HOUR)
{
return isFuture ? "in " + ts.Hours + " hours" : ts.Hours + " hours ago";
}
if (delta < 48 * HOUR)
{
return isFuture ? "tomorrow" : "yesterday";
}
if (delta < 30 * DAY)
{
return isFuture ? "in " + ts.Days + " days" : ts.Days + " days ago";
}
if (delta < 12 * MONTH)
{
int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return isFuture ? "in " + (months <= 1 ? "one month" : months + " months") : months <= 1 ? "one month ago" : months + " months ago";
}
else
{
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return isFuture ? "in " + (years <= 1 ? "one year" : years + " years") : years <= 1 ? "one year ago" : years + " years ago";
}
}
}
使用解构主义和Linq得到“n(最大时间单位)前”的“一行”:
TimeSpan timeSpan = DateTime.Now - new DateTime(1234, 5, 6, 7, 8, 9);
(string unit, int value) = new Dictionary<string, int>
{
{"year(s)", (int)(timeSpan.TotalDays / 365.25)}, //https://en.wikipedia.org/wiki/Year#Intercalation
{"month(s)", (int)(timeSpan.TotalDays / 29.53)}, //https://en.wikipedia.org/wiki/Month
{"day(s)", (int)timeSpan.TotalDays},
{"hour(s)", (int)timeSpan.TotalHours},
{"minute(s)", (int)timeSpan.TotalMinutes},
{"second(s)", (int)timeSpan.TotalSeconds},
{"millisecond(s)", (int)timeSpan.TotalMilliseconds}
}.First(kvp => kvp.Value > 0);
Console.WriteLine($"{value} {unit} ago");
你在786年前
当前年份和月份,如
TimeSpan timeSpan = DateTime.Now - new DateTime(2020, 12, 6, 7, 8, 9);
您4天前收到
实际日期,比如
TimeSpan timeSpan = DateTime.Now - DateTime.Now.Date;
9小时前到达
我是这样做的
var ts = new TimeSpan(DateTime.UtcNow.Ticks - dt.Ticks);
double delta = Math.Abs(ts.TotalSeconds);
if (delta < 60)
{
return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 60 * 2)
{
return "a minute ago";
}
if (delta < 45 * 60)
{
return ts.Minutes + " minutes ago";
}
if (delta < 90 * 60)
{
return "an hour ago";
}
if (delta < 24 * 60 * 60)
{
return ts.Hours + " hours ago";
}
if (delta < 48 * 60 * 60)
{
return "yesterday";
}
if (delta < 30 * 24 * 60 * 60)
{
return ts.Days + " days ago";
}
if (delta < 12 * 30 * 24 * 60 * 60)
{
int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return months <= 1 ? "one month ago" : months + " months ago";
}
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "one year ago" : years + " years ago";
建议?评论?如何改进此算法?