给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
给定特定的DateTime值,如何显示相对时间,例如:
2小时前3天前一个月前
当前回答
iPhone Objective-C版本
+ (NSString *)timeAgoString:(NSDate *)date {
int delta = -(int)[date timeIntervalSinceNow];
if (delta < 60)
{
return delta == 1 ? @"one second ago" : [NSString stringWithFormat:@"%i seconds ago", delta];
}
if (delta < 120)
{
return @"a minute ago";
}
if (delta < 2700)
{
return [NSString stringWithFormat:@"%i minutes ago", delta/60];
}
if (delta < 5400)
{
return @"an hour ago";
}
if (delta < 24 * 3600)
{
return [NSString stringWithFormat:@"%i hours ago", delta/3600];
}
if (delta < 48 * 3600)
{
return @"yesterday";
}
if (delta < 30 * 24 * 3600)
{
return [NSString stringWithFormat:@"%i days ago", delta/(24*3600)];
}
if (delta < 12 * 30 * 24 * 3600)
{
int months = delta/(30*24*3600);
return months <= 1 ? @"one month ago" : [NSString stringWithFormat:@"%i months ago", months];
}
else
{
int years = delta/(12*30*24*3600);
return years <= 1 ? @"one year ago" : [NSString stringWithFormat:@"%i years ago", years];
}
}
其他回答
在Java中有没有一种简单的方法可以做到这一点?java.util.Date类似乎相当有限。
下面是我的快速而肮脏的Java解决方案:
import java.util.Date;
import javax.management.timer.Timer;
String getRelativeDate(Date date) {
long delta = new Date().getTime() - date.getTime();
if (delta < 1L * Timer.ONE_MINUTE) {
return toSeconds(delta) == 1 ? "one second ago" : toSeconds(delta) + " seconds ago";
}
if (delta < 2L * Timer.ONE_MINUTE) {
return "a minute ago";
}
if (delta < 45L * Timer.ONE_MINUTE) {
return toMinutes(delta) + " minutes ago";
}
if (delta < 90L * Timer.ONE_MINUTE) {
return "an hour ago";
}
if (delta < 24L * Timer.ONE_HOUR) {
return toHours(delta) + " hours ago";
}
if (delta < 48L * Timer.ONE_HOUR) {
return "yesterday";
}
if (delta < 30L * Timer.ONE_DAY) {
return toDays(delta) + " days ago";
}
if (delta < 12L * 4L * Timer.ONE_WEEK) { // a month
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 long toSeconds(long date) {
return date / 1000L;
}
private long toMinutes(long date) {
return toSeconds(date) / 60L;
}
private long toHours(long date) {
return toMinutes(date) / 60L;
}
private long toDays(long date) {
return toHours(date) / 24L;
}
private long toMonths(long date) {
return toDays(date) / 30L;
}
private long toYears(long date) {
return toMonths(date) / 365L;
}
我是这样做的
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";
建议?评论?如何改进此算法?
Jeff,您的代码很好,但使用常量可以更清晰(如代码完成中所建议的)。
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 == 1 ? "one second ago" : ts.Seconds + " seconds ago";
if (delta < 2 * MINUTE)
return "a minute ago";
if (delta < 45 * MINUTE)
return ts.Minutes + " minutes ago";
if (delta < 90 * MINUTE)
return "an hour ago";
if (delta < 24 * HOUR)
return ts.Hours + " hours ago";
if (delta < 48 * HOUR)
return "yesterday";
if (delta < 30 * DAY)
return ts.Days + " days ago";
if (delta < 12 * 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";
}
我的方法要简单得多。您可以根据需要调整返回字符串
public static string TimeLeft(DateTime utcDate)
{
TimeSpan timeLeft = DateTime.UtcNow - utcDate;
string timeLeftString = "";
if (timeLeft.Days > 0)
{
timeLeftString += timeLeft.Days == 1 ? timeLeft.Days + " day" : timeLeft.Days + " days";
}
else if (timeLeft.Hours > 0)
{
timeLeftString += timeLeft.Hours == 1 ? timeLeft.Hours + " hour" : timeLeft.Hours + " hours";
}
else
{
timeLeftString += timeLeft.Minutes == 1 ? timeLeft.Minutes+" minute" : timeLeft.Minutes + " minutes";
}
return timeLeftString;
}
在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";
} ?>