咨询区
Jeff Atwood:
给定一个 DataTime
值,如何计算如下时间?比如说:
2 小时前?
3 天前?
1 个月前?
回答区
neuracnu:
我在 DateTime 类上做了一个扩展方法,你可以给它传递未来或者过去的时间,还可以给他传一个 approximation
选项来指定更精细的信息描述,参考如下代码:
using System.Text;/// <summary>
/// Compares a supplied date to the current date and generates a friendly English
/// comparison ("5 days ago", "5 days from now")
/// </summary>
/// <param name="date">The date to convert</param>
/// <param name="approximate">When off, calculate timespan down to the second.
/// When on, approximate to the largest round unit of time.</param>
/// <returns></returns>
public static string ToRelativeDateString(this DateTime value, bool approximate)
{StringBuilder sb = new StringBuilder();string suffix = (value > DateTime.Now) ? " from now" : " ago";TimeSpan timeSpan = new TimeSpan(Math.Abs(DateTime.Now.Subtract(value).Ticks));if (timeSpan.Days > 0){sb.AppendFormat("{0} {1}", timeSpan.Days,(timeSpan.Days > 1) ? "days" : "day");if (approximate) return sb.ToString() + suffix;}if (timeSpan.Hours > 0){sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty,timeSpan.Hours, (timeSpan.Hours > 1) ? "hours" : "hour");if (approximate) return sb.ToString() + suffix;}if (timeSpan.Minutes > 0){sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty, timeSpan.Minutes, (timeSpan.Minutes > 1) ? "minutes" : "minute");if (approximate) return sb.ToString() + suffix;}if (timeSpan.Seconds > 0){sb.AppendFormat("{0}{1} {2}", (sb.Length > 0) ? ", " : string.Empty, timeSpan.Seconds, (timeSpan.Seconds > 1) ? "seconds" : "second");if (approximate) return sb.ToString() + suffix;}if (sb.Length == 0) return "right now";sb.Append(suffix);return sb.ToString();
}
neuracnu:
github 上有一个非常流行的 DateTime 帮助类,可以非常精细化的满足你的要求,参见网址:https://github.com/FluentDateTime/FluentDateTime , 比如下面这些例子:
var dateTime1 = 2.Hours().Ago();
var dateTime2 = 3.Days().Ago();
var dateTime3 = 1.Months().Ago();
var dateTime4 = 5.Hours().FromNow();
var dateTime5 = 2.Weeks().FromNow();
var dateTime6 = 40.Seconds().FromNow();
leppie:
纯手工封装,用 SortedList 预先做一个映射,应该还是能够满足你的需求,参考如下代码。
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;
}
点评区
试用了下 FluentDateTime
,果然????????,强烈推荐大家使用。