给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
当前回答
@杰夫
我知道你的有点长。然而,随着对“昨天”和“几年”的支持,它似乎确实更为有力。但根据我的经验,当使用此选项时,用户最有可能在前30天内查看内容。只有真正的铁杆人才会在这之后出现。所以,我通常选择保持简短。
这是我目前在我的一个网站上使用的方法。这只返回相对的日期、小时和时间。然后用户必须在输出中加上“ago”。
public static string ToLongString(this TimeSpan time)
{
string output = String.Empty;
if (time.Days > 0)
output += time.Days + " days ";
if ((time.Days == 0 || time.Days == 1) && time.Hours > 0)
output += time.Hours + " hr ";
if (time.Days == 0 && time.Minutes > 0)
output += time.Minutes + " min ";
if (output.Length == 0)
output += time.Seconds + " sec";
return output.Trim();
}
其他回答
当然,解决“1小时前”问题的一个简单方法是增加“一小时前”有效的窗口。改变
if (delta < 5400) // 90 * 60
{
return "an hour ago";
}
into
if (delta < 7200) // 120 * 60
{
return "an hour ago";
}
这意味着110分钟前发生的事情将被解读为“一小时前”——这可能并不完美,但我认为这比“1小时前”的现状要好。
jquery.timeago插件
Jeff,因为Stack Overflow广泛使用jQuery,所以我建议使用jQuery.timeago插件。
优点:
即使页面是在10分钟前打开的,也不要使用“1分钟前”的时间戳;timeago自动刷新。您可以充分利用web应用程序中的页面和/或片段缓存,因为时间戳不是在服务器上计算的。你可以像酷孩子一样使用微格式。
只需将其附加到DOM就绪的时间戳:
jQuery(document).ready(function() {
jQuery('abbr.timeago').timeago();
});
这将在标题中使用timeago类和ISO 8601时间戳转换所有缩写元素:
<abbr class="timeago" title="2008-07-17T09:24:17Z">July 17, 2008</abbr>
变成这样:
<abbr class="timeago" title="July 17, 2008">4 months ago</abbr>
结果:4个月前。随着时间的推移,时间戳将自动更新。
免责声明:我写了这个插件,所以我有偏见。
聚会晚了几年,但我有一个要求,无论是过去还是将来的约会,都要这样做,所以我把杰夫和文森特的约会结合在一起。这是一场盛大的盛会!:)
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";
}
}
}
如果您想获得类似“2天4小时12分钟前”的输出,则需要一个时间跨度:
TimeSpan timeDiff = DateTime.Now-CreatedDate;
然后您可以访问您喜欢的值:
timeDiff.Days
timeDiff.Hours
等
简单且100%的工作解决方案。
处理过去和将来的时间。。以防万一
public string GetTimeSince(DateTime postDate)
{
string message = "";
DateTime currentDate = DateTime.Now;
TimeSpan timegap = currentDate - postDate;
if (timegap.Days > 365)
{
message = string.Format(L("Ago") + " {0} " + L("Years"), (((timegap.Days) / 30) / 12));
}
else if (timegap.Days > 30)
{
message = string.Format(L("Ago") + " {0} " + L("Months"), timegap.Days/30);
}
else if (timegap.Days > 0)
{
message = string.Format(L("Ago") + " {0} " + L("Days"), timegap.Days);
}
else if (timegap.Hours > 0)
{
message = string.Format(L("Ago") + " {0} " + L("Hours"), timegap.Hours);
}
else if (timegap.Minutes > 0)
{
message = string.Format(L("Ago") + " {0} " + L("Minutes"), timegap.Minutes);
}
else if (timegap.Seconds > 0)
{
message = string.Format(L("Ago") + " {0} " + L("Seconds"), timegap.Seconds);
}
// let's handle future times..just in case
else if (timegap.Days < -365)
{
message = string.Format(L("In") + " {0} " + L("Years"), (((Math.Abs(timegap.Days)) / 30) / 12));
}
else if (timegap.Days < -30)
{
message = string.Format(L("In") + " {0} " + L("Months"), ((Math.Abs(timegap.Days)) / 30));
}
else if (timegap.Days < 0)
{
message = string.Format(L("In") + " {0} " + L("Days"), Math.Abs(timegap.Days));
}
else if (timegap.Hours < 0)
{
message = string.Format(L("In") + " {0} " + L("Hours"), Math.Abs(timegap.Hours));
}
else if (timegap.Minutes < 0)
{
message = string.Format(L("In") + " {0} " + L("Minutes"), Math.Abs(timegap.Minutes));
}
else if (timegap.Seconds < 0)
{
message = string.Format(L("In") + " {0} " + L("Seconds"), Math.Abs(timegap.Seconds));
}
else
{
message = "a bit";
}
return message;
}