首页 文章

模糊数据算法

提问于
浏览
31

我正在寻找模糊日期算法 . 我刚刚开始写一个,并意识到它是一个繁琐的任务 . 它迅速退化为许多可怕的代码,以应对特殊情况,如“昨天”,“上周”和“上个月末”之间的差异,所有这些都可以(在某些情况下)指的是同一天但是个别正确根据今天的日期 .

我确信必须有一个开源模糊日期格式化器,但我找不到它 . 理想情况下,我喜欢使用NSDate(OSX / iPhone)及其格式化程序,但这并不困难 . 有没有人知道模糊日期格式化程序相对于现在采取任何时间段并返回像(但不限于)的字符串:

很久以前

  • 在最后五分钟

  • 今天早些时候

  • 今天早上
    昨晚

  • 上周

  • 上周三

  • 上个月初

  • 去年6月

  • 几年前

在一个理想的世界中,我希望字符串尽可能丰富(即在“刚刚之前”返回随机变体,例如“刚才”) .

澄清 . 我正在寻找比基本的buckts和字符串更微妙的东西 . 我想要知道“昨天”和“上周三”的东西都可以指同一时期,但只有一个是正确的,今天是星期四 .

14 回答

  • 1

    This question should get you started.它有这个网站用于计算其相对时间的代码 . 它可能没有您想要的特定范围,但是一旦您完成设置它们就很容易添加 .

  • 6

    NSDateFormatter中有一个属性 - “doesRelativeDateFormatting” . 它仅出现在10.6 / iOS4.0及更高版本中,但它会将日期格式化为正确语言环境中的相对日期 .

    来自Apple's Documentation

    如果日期格式化程序使用相对日期格式,则可能会使用短语(例如“今天”或“明天”)替换其输出的日期组件 - 表示相对日期 . 可用的短语取决于日期格式化程序的区域设置;然而,对于将来的日期,英语可能只允许“明天”,法语可能允许“后天的后天”,如下例所示 .

    代码

    以下是为给定语言环境打印出大量相对字符串的代码 .

    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;
    }
    

    笔记:

    • 不需要语言环境

    • 英语没有那么多替换 . 在撰写本文时,有:"Yesterday, Today, Tomorrow" . Apple可能会在未来包含更多内容 .

    • 更改区域设置并查看其他语言的可用内容非常有趣(例如,法语比英语更多)

    • 如果在iOS上,您可能想要订阅UIApplicationSignificantTimeChangeNotification

    Interface Builder

    您可以在Interface Builder中设置“doesRelativeDateFormatting”属性:

    • 选择您的NSDateFormatter并选择Inspector Palette的"Identity Inspector"选项卡(最后一个[command-6]) .

    • 在名为"User Defined Runtime Attributes"的子部分下,您可以为所选对象(在本例中为NSDateFormatter实例)上的键添加自己的值 . 添加"doesRelativeDateFormatting",选择"Boolean"类型,并确保选中它 .

    • Remember :看起来好像没有设置好 .

  • 8

    你可能想看看date_helper.rb中的Rail的 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
    
  • 0

    所以,这是我在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.
    }
    

    对不起发布这个花了这么长时间......

  • 1

    这是基于Pretty和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);
            }
        }
    }
    
  • 7

    我不确定你为什么说这是一个可怕的编码练习 . 每个返回字符串实际上是父集的子集,因此您可以在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"
    
  • 0

    根据我的经验,这些类型的日期生成器根本不是“模糊”的 . 实际上,它们只是一堆if语句的时间段 . 例如,任何小于30秒的时间都是“片刻之前”,360到390天是“一年前”等等 . 其中一些将使用目标日期来计算特殊名称(六月,周三等) . 很抱歉打破了你的幻想 .

  • 0

    不用说(但无论如何我会说)不要使用每年365天减少的where循环,即使在366天的闰年(或者你会发现自己在Zune开发者的行列)

    这是一个c#版本:

    http://tiredblogger.wordpress.com/2008/08/21/creating-twitter-esque-relative-dates-in-c/

  • 1

    我知道这样的时间最近变得非常受欢迎,但请考虑让它成为切换相对“模糊”日期和正常绝对日期的选项 .

    例如,知道5分钟前发表评论是有用的,但是告诉我评论A是4小时前而评论B是9小时前的时间是11点,而且我宁愿知道评论A是今天早上有人醒来时写的评论B是由熬夜的人写的(假设我知道他们在我的时区) .

    • 编辑:仔细观察你的问题,你似乎在一定程度上通过提及时间而不是“X前”来避免这种情况,但另一方面,如果用户处于不同的时间,你可能会给人一种错误的印象区域,因为您的“今天早晨”可能是在相关用户的半夜 .

    根据其他用户的时区,用相对时间来增加时间可能很酷,但这假设用户愿意提供它并且它是正确的 .

  • 12

    我对另一个问题的解决方案不满意 . 所以使用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";
    }
    
  • 1

    这几乎总是使用巨大的switch语句来完成,并且实现起来很简单 .

    请记住以下几点:

    • 始终首先测试最小的时间 Span

    • 不要忘记让你的字符串可以本地化 .

  • 0

    您可能会发现source from timeago很有用 . 该插件的描述是"a jQuery plugin that makes it easy to support automatically updating fuzzy timestamps (e.g. " 4分钟前" or "大约1天前")."

    它将's essentially a JavaScript port of Rail' s distance_of_time_in_words 函数塞进了一个jQuery插件 .

  • 6

    我的公司有this .NET library做了你想要的一些,它做了非常灵活的日期时间解析(包括一些相对格式),但它只做非相对输出 .

  • 3

    查看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
    

    https://github.com/wanasit/chrono

相关问题