我正在寻找模糊日期算法。我刚刚开始写一个,并意识到它是一个繁琐的任务。它迅速退化为许多可怕的代码,以应对特殊情况,如“昨天”,“上周”和“上个月末”之间的差异,所有这些都可以(在某些情况下)指的是同一天但是个别正确根据今天的日期。
我确信必须有一个开源模糊日期格式化程序,但我找不到它。理想情况下,我喜欢使用NSDate(OSX / iPhone)及其格式化程序,但这并不困难。有没有人知道模糊日期格式化程序相对于现在采取任何时间段并返回一个字符串(但不限于):
在一个理想的世界中,我希望字符串尽可能丰富(即在“刚才之前”返回随机变体,例如“刚才”)。
澄清。我正在寻找比基本的buckts和字符串更微妙的东西。我想要一些知道“昨天”和“上周三”的东西都可以指同一时期,但只有一个是正确的,今天是星期四。
答案 0 :(得分:12)
NSDateFormatter中有一个属性 - “doesRelativeDateFormatting”。它仅出现在10.6 / iOS4.0及更高版本中,但它会将日期格式化为正确语言环境中的相对日期。
如果日期格式化程序使用相对日期 格式化,在可能的情况下替换它 其输出的日期组件 短语 - 例如“今天”或 “明天” - 表示亲戚 日期。可用的短语取决于 日期格式化程序的语言环境; 而对于未来的日期, 英语可能只允许“明天” 法国人可能允许“后一天 后天,“如图所示 以下示例。
以下代码将打印出给定语言环境的大量相对字符串。
NSLocale *locale = [NSLocale currentLocale];
// NSLocale *locale = [[[NSLocale alloc] initWithLocaleIdentifier:@"fr_FR"] autorelease];
NSDateFormatter *relativeDateFormatter = [[NSDateFormatter alloc] init];
[relativeDateFormatter setTimeStyle:NSDateFormatterNoStyle];
[relativeDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[relativeDateFormatter setDoesRelativeDateFormatting:YES];
[relativeDateFormatter setLocale:locale];
NSDateFormatter *normalDateFormatter = [[NSDateFormatter alloc] init];
[normalDateFormatter setTimeStyle:NSDateFormatterNoStyle];
[normalDateFormatter setDateStyle:NSDateFormatterMediumStyle];
[normalDateFormatter setDoesRelativeDateFormatting:NO];
[normalDateFormatter setLocale:locale];
NSString * lastUniqueString = nil;
for ( NSTimeInterval timeInterval = -60*60*24*400; timeInterval < 60*60*24*400; timeInterval += 60.0*60.0*24.0 )
{
NSDate * date = [NSDate dateWithTimeIntervalSinceNow:timeInterval];
NSString * relativeFormattedString = [relativeDateFormatter stringForObjectValue:date];
NSString * formattedString = [normalDateFormatter stringForObjectValue:date];
if ( [relativeFormattedString isEqualToString:lastUniqueString] || [relativeFormattedString isEqualToString:formattedString] )
continue;
NSLog( @"%@", relativeFormattedString );
lastUniqueString = relativeFormattedString;
}
注意:
您可以在Interface Builder中设置“doesRelativeDateFormatting”属性:
答案 1 :(得分:9)
This question should get you started.它拥有此网站用于计算其相对时间的代码。它可能没有您想要的特定范围,但是一旦您完成设置它们就很容易添加。
答案 2 :(得分:7)
您可能希望查看我在date_helper.rb中使用的distance_of_time_in_words
功能,我已将其粘贴在下面。
# File vendor/rails/actionpack/lib/action_view/helpers/date_helper.rb, line 59
def distance_of_time_in_words(from_time, to_time = 0, include_seconds = false, options = {})
from_time = from_time.to_time if from_time.respond_to?(:to_time)
to_time = to_time.to_time if to_time.respond_to?(:to_time)
distance_in_minutes = (((to_time - from_time).abs)/60).round
distance_in_seconds = ((to_time - from_time).abs).round
I18n.with_options :locale => options[:locale], :scope => 'datetime.distance_in_words''datetime.distance_in_words' do |locale|
case distance_in_minutes
when 0..1
return distance_in_minutes == 0 ?
locale.t(:less_than_x_minutes, :count => 1) :
locale.t(:x_minutes, :count => distance_in_minutes) unless include_seconds
case distance_in_seconds
when 0..4 then locale.t :less_than_x_seconds, :count => 5
when 5..9 then locale.t :less_than_x_seconds, :count => 10
when 10..19 then locale.t :less_than_x_seconds, :count => 20
when 20..39 then locale.t :half_a_minute
when 40..59 then locale.t :less_than_x_minutes, :count => 1
else locale.t :x_minutes, :count => 1
end
when 2..44 then locale.t :x_minutes, :count => distance_in_minutes
when 45..89 then locale.t :about_x_hours, :count => 1
when 90..1439 then locale.t :about_x_hours, :count => (distance_in_minutes.to_f / 60.0).round
when 1440..2879 then locale.t :x_days, :count => 1
when 2880..43199 then locale.t :x_days, :count => (distance_in_minutes / 1440).round
when 43200..86399 then locale.t :about_x_months, :count => 1
when 86400..525599 then locale.t :x_months, :count => (distance_in_minutes / 43200).round
when 525600..1051199 then locale.t :about_x_years, :count => 1
else locale.t :over_x_years, :count => (distance_in_minutes / 525600).round
end
end
end
答案 3 :(得分:6)
所以,这是我在NSDate上为那些仍然感兴趣的人写的类别。问题是那些变得有点不切实际的问题之一。它基本上是一个巨大的开关声明(尽管我在一系列级联if()中实现它以使其更具可读性。
对于每个时间段,我然后从一组随机的时间中选择。
总而言之,这让我们的一些用户感到高兴,但我不确定这是值得的。
NSTimeInterval const kTenSeconds = (10.0f );
NSTimeInterval const kOneMinute = (60.0f);
NSTimeInterval const kFiveMinutes = (5.0f*60.0f);
NSTimeInterval const kFifteenMinutes = (15.0f*60.0f) ;
NSTimeInterval const kHalfAnHour = (30.0f*60.0f) ;
NSTimeInterval const kOneHour = 3600.0f; // (60.0f * 60.0f);
NSTimeInterval const kHalfADay = (3600.0f * 12.0f);
NSTimeInterval const kOneDay = (3600.0f * 24.0f);
NSTimeInterval const kOneWeek = (3600.0f * 24.0f * 7.0f);
@implementation NSDate (Fuzzy)
-(NSString*)fuzzyStringRelativeToNow;
{
static NSArray* secondsStrings;
static NSArray* minuteStrings;
static NSArray* fiveMinuteStrings;
static NSArray* halfHourStrings;
static NSArray* earlyMonthStrings;
NSTimeInterval timeFromNow = [self timeIntervalSinceNow];
if((timeFromNow < 0)) // In the past
{
timeFromNow = - timeFromNow;
if ( (timeFromNow < kTenSeconds))
{
if(!secondsStrings)
{
secondsStrings = [[NSArray arrayWithObjects:@"just now",
//@"a few seconds ago",
//@"right this instant",
@"moments ago",
nil] retain];
}
unsigned int index = random() % ([secondsStrings count] - 1);
return [secondsStrings objectAtIndex:index];
}
if ( (timeFromNow < kOneMinute))
{
if(!minuteStrings)
{
minuteStrings = [[NSArray arrayWithObjects:@"just now",
@"very recently",
@"in the last minute",
nil] retain];
}
unsigned int index = random() % ([minuteStrings count] - 1);
return [minuteStrings objectAtIndex:index];
}
if (timeFromNow < kFiveMinutes)
{
if(!fiveMinuteStrings)
{
fiveMinuteStrings = [[NSArray arrayWithObjects:@"just now",
@"very recently",
//@"in the last minute",
@"a few minutes ago",
//@"in the last five minutes",
nil] retain];
}
unsigned int index = random() % ([fiveMinuteStrings count] - 1);
return [fiveMinuteStrings objectAtIndex:index];
}
if (timeFromNow < kFifteenMinutes)
{
return @"in the last 15 minutes";
}
if (timeFromNow < kHalfAnHour)
{
if(!halfHourStrings)
{
halfHourStrings = [[NSArray arrayWithObjects:@"in the last half hour",
//@"in the last half an hour",
@"in the last 30 minutes",
//@"about half an hour ago",
@"fairly recently",
nil] retain];
}
unsigned int index = random() % ([halfHourStrings count] - 1);
return [halfHourStrings objectAtIndex:index];
}
if (timeFromNow < kOneHour)
{
return @"in the last hour";
}
if ((timeFromNow < (kOneHour + kFiveMinutes)) && (timeFromNow > (kOneHour - kFiveMinutes)))
{
return @"about an hour ago";
}
if((timeFromNow < ((kOneHour*2.0f) + kFiveMinutes ))&& (timeFromNow > ((kOneHour*2.0f) - kFiveMinutes)))
{
return @"a couple of hours ago";
}
// Now we're over an hour, we need to calculate a few specific dates to compare against
NSDate *today = [NSDate date];
NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;
NSDateComponents* todayComponents = [gregorian components:unitFlags fromDate:today];
todayComponents.hour = 12;
NSDate* noonToday = [gregorian dateFromComponents:todayComponents];
NSTimeInterval timeSinceNoonToday = [self timeIntervalSinceDate:noonToday];
if (timeSinceNoonToday > 0) // sometime since noon
{
if (timeSinceNoonToday > kOneHour * 9) // i.e. after 9pm today
return @"earlier tonight";
if (timeSinceNoonToday > kOneHour * 7) // i.e. after 7pm today
return @"earlier this evening";
if (timeSinceNoonToday < kOneHour * 1) // between noon and 1pm
return @"early this afternoon";
return @"this afternoon";
}
NSTimeInterval timeSinceMidnight = kHalfADay -timeSinceNoonToday; // Note sign is reversed.
if ((timeSinceNoonToday < 0) & (timeSinceNoonToday > -kHalfADay)) // between midnight and noon today
{
if (timeSinceMidnight < kFiveMinutes)
return @"around midnight";
if (timeSinceMidnight < kOneHour * 2) // up to 2am
return @"very early this morning";
if (timeSinceMidnight < kOneHour * 5) // up to 5am
return @"early this morning";
else if (timeSinceMidnight < kOneHour * 11)
return @"late this morning";
else
return @"this morning";
}
// NSTimeInterval timeSinceNoonYesterday = timeSinceNoonToday - kOneDay;
// timeSinceMidnight = -timeSinceMidnight;
if (timeSinceMidnight < kOneHour * 24) // not the day before...
{
if (timeSinceMidnight < kFiveMinutes)
return @"around midnight";
if (timeSinceMidnight < kFifteenMinutes)
return @"just before midnight";
if (timeSinceMidnight < kOneHour * 2) // after 10pm
return @"late last night";
if (timeSinceMidnight < kOneHour * 5) // After 7
return @"yesterday evening";
else if (timeSinceMidnight < kOneHour * 7)
return @"yesterday evening"; // after 5pm
else if (timeSinceMidnight < kOneHour * 7)
return @"yesterday evening"; // after 5pm
else if (timeSinceMidnight < kOneHour * 10)
return @"yesterday afternoon"; // after 5pm
else if (timeSinceMidnight < kOneHour * 12)
return @"early yesterday afternoon"; // before 1pm
else if (timeSinceMidnight < kOneHour * 13)
return @"late yesterday morning"; // after 11m
else if (timeSinceMidnight < kOneHour * 17)
return @"yesterday morning";
else
return @"early yesterday morning";
}
NSDateFormatter* formatter = [[[NSDateFormatter alloc] init] autorelease];
int integerSeconds = timeSinceMidnight;
int integerDay = kOneDay;
int secondsIntoDay = integerSeconds % integerDay;
NSString* formatString = @"last %@";
if (timeFromNow < kOneWeek)
{
if (secondsIntoDay < kFifteenMinutes)
formatString = @"around midnight on %@";
//else if (secondsIntoDay < kFifteenMinutes)
// formatString = @"just before midnight on %@";
else if (secondsIntoDay < kOneHour * 2) // after 10pm
formatString = @"late on %@ night";
else if (secondsIntoDay < kOneHour * 5) // After 7
formatString = @"on %@ evening";
else if (secondsIntoDay < kOneHour * 10)
formatString = @"on %@ afternoon"; // after 5pm
else if (secondsIntoDay < kOneHour * 12)
formatString = @"early on %@ afternoon"; // before 1pm
else if (secondsIntoDay < kOneHour * 13)
formatString = @"late on %@ morning"; // after 11am
else if (secondsIntoDay < kOneHour * 17)
formatString = @"on %@ morning";
else if (secondsIntoDay < kOneHour * 24) // not the day before...
formatString = @"early on %@ morning";
[formatter setDateFormat:@"EEEE"]; /// EEEE is long format of day of the week see: http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
return [NSString stringWithFormat:formatString, [formatter stringFromDate: self]];
}
//formatString = @"on %@ the week before last";
/*if (secondsIntoDay < kOneHour * 2) // after 10pm
formatString = @"early on %@ the week before last";
else if (timeSinceMidnight > kOneHour * 13)
formatString = @"late on %@ the week before last"; // after 11m*/
//if (timeFromNow < kOneWeek * 2)
//{
// [formatter setDateFormat:@"EEE"]; /// EEE is short format of day of the week see: http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
// return [NSString stringWithFormat:formatString, [formatter stringFromDate: self]];
//}
if (timeFromNow < kOneWeek * 2)
{
return @"the week before last";
}
NSDateComponents* myComponents = [gregorian components:unitFlags fromDate:self];
int monthsAgo = myComponents.month - todayComponents.month;
int yearsAgo = myComponents.year - todayComponents.year;
if (yearsAgo == 0)
{
if (monthsAgo == 0)
{
if(myComponents.day > 22)
return @"late this month";
if(myComponents.day < 7)
{
if(!earlyMonthStrings)
{
earlyMonthStrings = [[NSArray arrayWithObjects:@"earlier this month",
//@"at the beginning of the month",
@"early this month",
nil] retain];
}
unsigned int index = random() % ([earlyMonthStrings count] - 1);
return [earlyMonthStrings objectAtIndex:index];
}
return @"earlier this month";
}
if (monthsAgo == 1)
{
if(myComponents.day > 22)
return @"late last month";
if(myComponents.day < 7)
return @"early last month";
return @"last month";
}
formatString = @"in %@ this year";
/*if(myComponents.day > 22)
formatString = @"late in %@ this year";
if(myComponents.day < 7)
formatString = @"early in %@ this year";*/
[formatter setDateFormat:@"MMMM"]; /// MMM is longformat of month see: http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
return [NSString stringWithFormat:formatString, [formatter stringFromDate: self]];
}
if (yearsAgo == 1)
{
formatString = @"in %@ last year";
/*if(myComponents.day > 22)
formatString = @"late in %@ last year";
if(myComponents.day < 7)
formatString = @"late in %@ last year";*/
[formatter setDateFormat:@"MMM"]; /// MMM is longformat of month see: http://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns
return [NSString stringWithFormat:formatString, [formatter stringFromDate: self]];
}
// int daysAgo = integerSeconds / integerDay;
// Nothing yet...
[formatter setDateStyle:kCFDateFormatterMediumStyle];
//[formatter setTimeStyle:kCFDateFormatterShortStyle];
return [NSString stringWithFormat:@"on %@",[formatter stringFromDate: self]];
}
else
if(timeFromNow > 0) // The future
{
AICLog(kErrorLogEntry, @"FuzzyDates: Time marked as in the future: referenced date is %@, local time is %@", self, [NSDate date]);
return @"moments ago";
}
else
return @"right now"; // this seems unlikely.
return [self description]; // should never get here.
}
抱歉发布此内容花了这么长时间......
答案 4 :(得分:6)
这是基于Pretty and Humane日期和代码中的代码。时间线程。我添加了“上周一,下午5点”的处理,因为我喜欢它超过x天前。这可以处理过去和未来几个世纪。我热衷于国际化方面,所以最终需要做更多的工作。计算在当地时区。
public static class DateTimePretty
{
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 WEEK = 7 * DAY;
private const int MONTH = 30 * DAY;
private const int YEAR = 365;
const string now = "just now";
const string secondsFuture = "in {0} seconds", secondsPast = "{0} seconds ago";
const string minuteFuture = "in about a minute", minutePast = "about a minute ago";
const string minutesFuture = "in about {0} minutes", minutesPast = "about {0} minutes ago";
const string hourFuture = "in about an hour", hourPast = "about an hour ago";
const string hoursFuture = "in about {0} hours", hoursPast = "about {0} hours ago";
const string tomorrow = "tomorrow, {0}", yesterday = "yesterday, {0}";
const string nextDay = "{0}", nextWeekDay = "next {0}", lastDay = "last {0}";
//const string daysFuture = "in about {0} days", daysPast = "about {0} days ago";
const string weekFuture = "in about a week", weekPast = "about a week ago";
const string weeksFuture = "in about {0} weeks", weeksPast = "about {0} weeks ago";
const string monthFuture = "in about a month", monthPast = "about a month ago";
const string monthsFuture = "in about {0} months", monthsPast = "about {0} months ago";
const string yearFuture = "in about a year", yearPast = "about a year ago";
const string yearsFuture = "in about {0} years", yearsPast = "about {0} years ago";
const string centuryFuture = "in about a century", centuryPast = "about a century ago";
const string centuriesFuture = "in about {0} centuries", centuriesPast = "about {0} centuries ago";
/// <summary>
/// Returns a pretty version of the provided DateTime: "42 years ago", or "in 9 months".
/// </summary>
/// <param name="dateTime">DateTime in local time format, not Utc</param>
/// <returns>A pretty string</returns>
public static string GetPrettyDate(DateTime dateTime)
{
DateTime dateTimeNow = DateTime.Now;
bool isFuture = (dateTimeNow.Ticks < dateTime.Ticks);
var ts = isFuture ? new TimeSpan(dateTime.Ticks - dateTimeNow.Ticks) : new TimeSpan(dateTimeNow.Ticks - dateTime.Ticks);
double delta = ts.TotalSeconds;
if (delta < 10)
return now;
if (delta < 1 * MINUTE)
return isFuture ? string.Format(secondsFuture, ts.Seconds) : string.Format(secondsPast, ts.Seconds);
if (delta < 2 * MINUTE)
return isFuture ? minuteFuture : minutePast;
if (delta < 45 * MINUTE)
return isFuture ? string.Format(minutesFuture, ts.Minutes) : string.Format(minutesPast, ts.Minutes);
if (delta < 2 * HOUR)
return isFuture ? hourFuture : hourPast;
if (delta < 7 * DAY)
{
string shortTime = DateTimeFormatInfo.CurrentInfo.ShortTimePattern;
string shortWeekdayTime = "dddd, " + shortTime;
int dtDay = (int) dateTime.DayOfWeek;
int nowDay = (int) dateTimeNow.DayOfWeek;
if (isFuture)
{
if (dtDay == nowDay)
{
if (delta < DAY)
return string.Format(hoursFuture, ts.Hours);
else
return string.Format(nextWeekDay, dateTime.ToString(shortWeekdayTime));
}
else if (dtDay - nowDay == 1 || dtDay - nowDay == -6)
return string.Format(tomorrow, dateTime.ToString(shortTime));
else
return string.Format(nextDay, dateTime.ToString(shortWeekdayTime));
}
else
{
if (dtDay == nowDay)
{
if (delta < DAY)
return string.Format(hoursPast, ts.Hours);
else
return string.Format(lastDay, dateTime.ToString(shortWeekdayTime));
}
else if (nowDay - dtDay == 1 || nowDay - dtDay == -6)
return string.Format(yesterday, dateTime.ToString(shortTime));
else
return string.Format(lastDay, dateTime.ToString(shortWeekdayTime));
}
}
//if (delta < 7 * DAY)
// return isFuture ? string.Format(daysFuture, ts.Days) : string.Format(daysPast, ts.Days);
if (delta < 4 * WEEK)
{
int weeks = Convert.ToInt32(Math.Floor((double) ts.Days / 30));
if (weeks <= 1)
return isFuture ? weekFuture : weekPast;
else
return isFuture ? string.Format(weeksFuture, weeks) : string.Format(weeksPast, weeks);
}
if (delta < 12 * MONTH)
{
int months = Convert.ToInt32(Math.Floor((double) ts.Days / 30));
if (months <= 1)
return isFuture ? monthFuture : monthPast;
else
return isFuture ? string.Format(monthsFuture, months) : string.Format(monthsPast, months);
}
// Switch to days to avoid overflow
delta = ts.TotalDays;
if (delta < 100 * YEAR)
{
int years = Convert.ToInt32(Math.Floor((double) ts.TotalDays / 365.25));
if (years <= 1)
return isFuture ? yearFuture : yearPast;
else
return isFuture ? string.Format(yearsFuture, years) : string.Format(yearsPast, years);
}
else
{
int centuries = Convert.ToInt32(Math.Floor((double) ts.TotalDays / 365.2425));
if (centuries <= 1)
return isFuture ? centuryFuture : centuryPast;
else
return isFuture ? string.Format(centuriesFuture, centuries) : string.Format(centuriesPast, centuries);
}
}
}
答案 5 :(得分:3)
我不确定你为什么说这是一个可怕的编码练习。每个返回字符串实际上是父集的子集,因此您可以在if / elseif链中非常优雅地执行此操作。
if timestamp < 5sec
"A moment ago"
elseif timestamp < 5min
"Few minutes ago"
elseif timestamp < 12hr && timestamp < noon
"Today Morning"
...
elseif timestamp < 1week
"Few days ago"
elseif timestamp < 1month
"Few weeks ago"
elseif timestamp < 6month
"Few Months ago"
...
else
"Really really long time ago"
答案 6 :(得分:1)
根据我的经验,这些类型的日期生成器根本不是“模糊”的。实际上,它们只是一堆if语句的时间段。例如,任何小于30秒的时间都是“很久以前”,360到390天是“仅一年前”,等等。其中一些将使用目标日期来计算特殊名称(6月,星期三等)。 很抱歉打破了你的幻想。
答案 7 :(得分:1)
不用说(但无论如何我会说)不要使用where循环,即使在366天的闰年,每年减少365天(或者你会发现自己在Zune开发者的行列中)< / p>
这是一个c#版本:
http://tiredblogger.wordpress.com/2008/08/21/creating-twitter-esque-relative-dates-in-c/
答案 8 :(得分:1)
我知道这样的时间最近变得非常流行,但请考虑让它成为切换相对“模糊”日期和正常绝对日期的选项。
例如,知道5分钟前发表评论很有用,但是告诉我评论A是4小时前评论B并且评论B是9小时前的时间是上午11点,而且我宁愿知道评论A是在今天早上有人醒来时写的,评论B是由熬夜的人写的(假设我知道他们在我的时区)。
- 编辑:仔细看看你的问题,你似乎在某种程度上通过提及时间而不是“X前”来避免这种情况,但另一方面,如果用户处于不同的时区,你可能会给人一种错误的印象,因为你的“今天早晨”可能是在相关用户的半夜。
根据其他用户的时区,用相对时间来增加时间可能很酷,但这假设用户愿意提供它并且它是正确的。
答案 9 :(得分:1)
我对另一个问题的解决方案不满意。所以使用Date时间类创建了我自己的。 IMO,它更清洁。在我的测试中,它像我想要的那样工作。希望这有助于某人。
DateTime now = DateTime.Now;
long nowticks = now.Ticks;
long thenticks = dt.Ticks;
long diff = nowticks - thenticks;
DateTime n = new DateTime(diff);
if (n.Year > 1)
{
return n.Year.ToString() + " years ago";
}
else if (n.Month > 1)
{
return n.Month.ToString() + " months ago";
}
else if (n.Day > 1)
{
return n.Day.ToString() + " days ago";
}
else if (n.Hour > 1)
{
return n.Hour.ToString() + " hours ago";
}
else if (n.Minute > 1)
{
return n.Minute.ToString() + " minutes ago";
}
else
{
return n.Second.ToString() + " seconds ago";
}
答案 10 :(得分:0)
这几乎总是使用一个巨大的switch语句完成,并且很容易实现。
请记住以下几点:
答案 11 :(得分:0)
您可能会发现source from timeago很有用。该插件的描述是“一个jQuery插件,可以很容易地支持自动更新模糊时间戳(例如”4分钟前或“约1天前”)。“
它本质上是一个嵌入jQuery插件的Rail distance_of_time_in_words
函数的JavaScript端口。
答案 12 :(得分:0)
我的公司this .NET library做了一些你想做的事情,因为它做了非常灵活的日期时间解析(包括一些相对格式),但它只做非相对输出。
答案 13 :(得分:0)
查看Chrono的Javascript启发式日期解析器。
Chrono支持大多数日期和时间格式,例如:
Today, Tomorrow, Yesterday, Last Friday, etc
17 August 2013 - 19 August 2013
This Friday from 13:00 - 16.00
5 days ago
Sat Aug 17 2013 18:40:39 GMT+0900 (JST)
2014-11-30T08:15:30-05:30