给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
当前回答
用于客户端gwt的Java:
import java.util.Date;
public class RelativeDateFormat {
private static final long ONE_MINUTE = 60000L;
private static final long ONE_HOUR = 3600000L;
private static final long ONE_DAY = 86400000L;
private static final long ONE_WEEK = 604800000L;
public static String format(Date date) {
long delta = new Date().getTime() - date.getTime();
if (delta < 1L * ONE_MINUTE) {
return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta)
+ " seconds ago";
}
if (delta < 2L * ONE_MINUTE) {
return "one minute ago";
}
if (delta < 45L * ONE_MINUTE) {
return toMinutes(delta) + " minutes ago";
}
if (delta < 90L * ONE_MINUTE) {
return "one hour ago";
}
if (delta < 24L * ONE_HOUR) {
return toHours(delta) + " hours ago";
}
if (delta < 48L * ONE_HOUR) {
return "yesterday";
}
if (delta < 30L * ONE_DAY) {
return toDays(delta) + " days ago";
}
if (delta < 12L * 4L * ONE_WEEK) {
long months = toMonths(delta);
return months <= 1 ? "one month ago" : months + " months ago";
} else {
long years = toYears(delta);
return years <= 1 ? "one year ago" : years + " years ago";
}
}
private static long toSeconds(long date) {
return date / 1000L;
}
private static long toMinutes(long date) {
return toSeconds(date) / 60L;
}
private static long toHours(long date) {
return toMinutes(date) / 60L;
}
private static long toDays(long date) {
return toHours(date) / 24L;
}
private static long toMonths(long date) {
return toDays(date) / 30L;
}
private static long toYears(long date) {
return toMonths(date) / 365L;
}
}
其他回答
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在他的博客上写了一篇文章
我是这样做的
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";
建议?评论?如何改进此算法?
您可以使用TimeAgo扩展,如下所示:
public static string TimeAgo(this DateTime dateTime)
{
string result = string.Empty;
var timeSpan = DateTime.Now.Subtract(dateTime);
if (timeSpan <= TimeSpan.FromSeconds(60))
{
result = string.Format("{0} seconds ago", timeSpan.Seconds);
}
else if (timeSpan <= TimeSpan.FromMinutes(60))
{
result = timeSpan.Minutes > 1 ?
String.Format("about {0} minutes ago", timeSpan.Minutes) :
"about a minute ago";
}
else if (timeSpan <= TimeSpan.FromHours(24))
{
result = timeSpan.Hours > 1 ?
String.Format("about {0} hours ago", timeSpan.Hours) :
"about an hour ago";
}
else if (timeSpan <= TimeSpan.FromDays(30))
{
result = timeSpan.Days > 1 ?
String.Format("about {0} days ago", timeSpan.Days) :
"yesterday";
}
else if (timeSpan <= TimeSpan.FromDays(365))
{
result = timeSpan.Days > 30 ?
String.Format("about {0} months ago", timeSpan.Days / 30) :
"about a month ago";
}
else
{
result = timeSpan.Days > 365 ?
String.Format("about {0} years ago", timeSpan.Days / 365) :
"about a year ago";
}
return result;
}
或者使用带有Timeago的Razor扩展的jQuery插件。
鉴于全世界和她的丈夫似乎都在发布代码样本,这是我不久前根据这些答案写的。
我特别需要这个代码可以本地化。所以我有两个类——Grammar,它指定了可本地化的术语,FuzzyDateExtensions,它包含一系列扩展方法。我不需要处理未来的日期时间,因此不尝试使用此代码处理它们。
为了简洁起见,我在源代码中保留了一些XMLdoc,但删除了大部分(显而易见的地方)。我也没有把每个班级成员都包括在这里:
public class Grammar
{
/// <summary> Gets or sets the term for "just now". </summary>
public string JustNow { get; set; }
/// <summary> Gets or sets the term for "X minutes ago". </summary>
/// <remarks>
/// This is a <see cref="String.Format"/> pattern, where <c>{0}</c>
/// is the number of minutes.
/// </remarks>
public string MinutesAgo { get; set; }
public string OneHourAgo { get; set; }
public string HoursAgo { get; set; }
public string Yesterday { get; set; }
public string DaysAgo { get; set; }
public string LastMonth { get; set; }
public string MonthsAgo { get; set; }
public string LastYear { get; set; }
public string YearsAgo { get; set; }
/// <summary> Gets or sets the term for "ages ago". </summary>
public string AgesAgo { get; set; }
/// <summary>
/// Gets or sets the threshold beyond which the fuzzy date should be
/// considered "ages ago".
/// </summary>
public TimeSpan AgesAgoThreshold { get; set; }
/// <summary>
/// Initialises a new <see cref="Grammar"/> instance with the
/// specified properties.
/// </summary>
private void Initialise(string justNow, string minutesAgo,
string oneHourAgo, string hoursAgo, string yesterday, string daysAgo,
string lastMonth, string monthsAgo, string lastYear, string yearsAgo,
string agesAgo, TimeSpan agesAgoThreshold)
{ ... }
}
FuzzyDateString类包含:
public static class FuzzyDateExtensions
{
public static string ToFuzzyDateString(this TimeSpan timespan)
{
return timespan.ToFuzzyDateString(new Grammar());
}
public static string ToFuzzyDateString(this TimeSpan timespan,
Grammar grammar)
{
return GetFuzzyDateString(timespan, grammar);
}
public static string ToFuzzyDateString(this DateTime datetime)
{
return (DateTime.Now - datetime).ToFuzzyDateString();
}
public static string ToFuzzyDateString(this DateTime datetime,
Grammar grammar)
{
return (DateTime.Now - datetime).ToFuzzyDateString(grammar);
}
private static string GetFuzzyDateString(TimeSpan timespan,
Grammar grammar)
{
timespan = timespan.Duration();
if (timespan >= grammar.AgesAgoThreshold)
{
return grammar.AgesAgo;
}
if (timespan < new TimeSpan(0, 2, 0)) // 2 minutes
{
return grammar.JustNow;
}
if (timespan < new TimeSpan(1, 0, 0)) // 1 hour
{
return String.Format(grammar.MinutesAgo, timespan.Minutes);
}
if (timespan < new TimeSpan(1, 55, 0)) // 1 hour 55 minutes
{
return grammar.OneHourAgo;
}
if (timespan < new TimeSpan(12, 0, 0) // 12 hours
&& (DateTime.Now - timespan).IsToday())
{
return String.Format(grammar.HoursAgo, timespan.RoundedHours());
}
if ((DateTime.Now.AddDays(1) - timespan).IsToday())
{
return grammar.Yesterday;
}
if (timespan < new TimeSpan(32, 0, 0, 0) // 32 days
&& (DateTime.Now - timespan).IsThisMonth())
{
return String.Format(grammar.DaysAgo, timespan.RoundedDays());
}
if ((DateTime.Now.AddMonths(1) - timespan).IsThisMonth())
{
return grammar.LastMonth;
}
if (timespan < new TimeSpan(365, 0, 0, 0, 0) // 365 days
&& (DateTime.Now - timespan).IsThisYear())
{
return String.Format(grammar.MonthsAgo, timespan.RoundedMonths());
}
if ((DateTime.Now - timespan).AddYears(1).IsThisYear())
{
return grammar.LastYear;
}
return String.Format(grammar.YearsAgo, timespan.RoundedYears());
}
}
我想实现的一件关键事情,以及本地化,就是“今天”只意味着“这个日历日”,所以IsToday、IsThisMonth和IsThisYear方法如下:
public static bool IsToday(this DateTime date)
{
return date.DayOfYear == DateTime.Now.DayOfYear && date.IsThisYear();
}
舍入方法如下(我已包括RoundedMonths,因为这有点不同):
public static int RoundedDays(this TimeSpan timespan)
{
return (timespan.Hours > 12) ? timespan.Days + 1 : timespan.Days;
}
public static int RoundedMonths(this TimeSpan timespan)
{
DateTime then = DateTime.Now - timespan;
// Number of partial months elapsed since 1 Jan, AD 1 (DateTime.MinValue)
int nowMonthYears = DateTime.Now.Year * 12 + DateTime.Now.Month;
int thenMonthYears = then.Year * 12 + then.Month;
return nowMonthYears - thenMonthYears;
}
我希望人们觉得这很有用和/或有趣:o)
我将为此提供一些方便的扩展方法,并使代码更可读。首先,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