给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
当前回答
在PHP中,我是这样做的:
<?php
function timesince($original) {
// array of time period chunks
$chunks = array(
array(60 * 60 * 24 * 365 , 'year'),
array(60 * 60 * 24 * 30 , 'month'),
array(60 * 60 * 24 * 7, 'week'),
array(60 * 60 * 24 , 'day'),
array(60 * 60 , 'hour'),
array(60 , 'minute'),
);
$today = time(); /* Current unix time */
$since = $today - $original;
if($since > 604800) {
$print = date("M jS", $original);
if($since > 31536000) {
$print .= ", " . date("Y", $original);
}
return $print;
}
// $j saves performing the count function each time around the loop
for ($i = 0, $j = count($chunks); $i < $j; $i++) {
$seconds = $chunks[$i][0];
$name = $chunks[$i][1];
// finding the biggest chunk (if the chunk fits, break)
if (($count = floor($since / $seconds)) != 0) {
break;
}
}
$print = ($count == 1) ? '1 '.$name : "$count {$name}s";
return $print . " ago";
} ?>
其他回答
你可以试试这个。我想它会正常工作的。
long delta = new Date().getTime() - date.getTime();
const int SECOND = 1;
const int MINUTE = 60 * SECOND;
const int HOUR = 60 * MINUTE;
const int DAY = 24 * HOUR;
const int MONTH = 30 * DAY;
if (delta < 0L)
{
return "not yet";
}
if (delta < 1L * MINUTE)
{
return ts.Seconds == 1 ? "one second ago" : ts.Seconds + " seconds ago";
}
if (delta < 2L * MINUTE)
{
return "a minute ago";
}
if (delta < 45L * MINUTE)
{
return ts.Minutes + " minutes ago";
}
if (delta < 90L * MINUTE)
{
return "an hour ago";
}
if (delta < 24L * HOUR)
{
return ts.Hours + " hours ago";
}
if (delta < 48L * HOUR)
{
return "yesterday";
}
if (delta < 30L * DAY)
{
return ts.Days + " days ago";
}
if (delta < 12L * MONTH)
{
int months = Convert.ToInt32(Math.Floor((double)ts.Days / 30));
return months <= 1 ? "one month ago" : months + " months ago";
}
else
{
int years = Convert.ToInt32(Math.Floor((double)ts.Days / 365));
return years <= 1 ? "one year ago" : years + " years ago";
}
/**
* {@code date1} has to be earlier than {@code date2}.
*/
public static String relativize(Date date1, Date date2) {
assert date2.getTime() >= date1.getTime();
long duration = date2.getTime() - date1.getTime();
long converted;
if ((converted = TimeUnit.MILLISECONDS.toDays(duration)) > 0) {
return String.format("%d %s ago", converted, converted == 1 ? "day" : "days");
} else if ((converted = TimeUnit.MILLISECONDS.toHours(duration)) > 0) {
return String.format("%d %s ago", converted, converted == 1 ? "hour" : "hours");
} else if ((converted = TimeUnit.MILLISECONDS.toMinutes(duration)) > 0) {
return String.format("%d %s ago", converted, converted == 1 ? "minute" : "minutes");
} else if ((converted = TimeUnit.MILLISECONDS.toSeconds(duration)) > 0) {
return String.format("%d %s ago", converted, converted == 1 ? "second" : "seconds");
} else {
return "just now";
}
}
我也建议在客户端进行计算。服务器工作更少。
以下是我使用的版本(来自Zach Leatherman)
/*
* Javascript Humane Dates
* Copyright (c) 2008 Dean Landolt (deanlandolt.com)
* Re-write by Zach Leatherman (zachleat.com)
*
* Adopted from the John Resig's pretty.js
* at http://ejohn.org/blog/javascript-pretty-date
* and henrah's proposed modification
* at http://ejohn.org/blog/javascript-pretty-date/#comment-297458
*
* Licensed under the MIT license.
*/
function humane_date(date_str){
var time_formats = [
[60, 'just now'],
[90, '1 minute'], // 60*1.5
[3600, 'minutes', 60], // 60*60, 60
[5400, '1 hour'], // 60*60*1.5
[86400, 'hours', 3600], // 60*60*24, 60*60
[129600, '1 day'], // 60*60*24*1.5
[604800, 'days', 86400], // 60*60*24*7, 60*60*24
[907200, '1 week'], // 60*60*24*7*1.5
[2628000, 'weeks', 604800], // 60*60*24*(365/12), 60*60*24*7
[3942000, '1 month'], // 60*60*24*(365/12)*1.5
[31536000, 'months', 2628000], // 60*60*24*365, 60*60*24*(365/12)
[47304000, '1 year'], // 60*60*24*365*1.5
[3153600000, 'years', 31536000], // 60*60*24*365*100, 60*60*24*365
[4730400000, '1 century'] // 60*60*24*365*100*1.5
];
var time = ('' + date_str).replace(/-/g,"/").replace(/[TZ]/g," "),
dt = new Date,
seconds = ((dt - new Date(time) + (dt.getTimezoneOffset() * 60000)) / 1000),
token = ' ago',
i = 0,
format;
if (seconds < 0) {
seconds = Math.abs(seconds);
token = '';
}
while (format = time_formats[i++]) {
if (seconds < format[0]) {
if (format.length == 2) {
return format[1] + (i > 1 ? token : ''); // Conditional so we don't return Just Now Ago
} else {
return Math.round(seconds / format[2]) + ' ' + format[1] + (i > 1 ? token : '');
}
}
}
// overflow for centuries
if(seconds > 4730400000)
return Math.round(seconds / 4730400000) + ' centuries' + token;
return date_str;
};
if(typeof jQuery != 'undefined') {
jQuery.fn.humane_dates = function(){
return this.each(function(){
var date = humane_date(this.title);
if(date && jQuery(this).text() != date) // don't modify the dom if we don't have to
jQuery(this).text(date);
});
};
}
我将为此提供一些方便的扩展方法,并使代码更可读。首先,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
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;
}