문제

퍼지 날짜 알고리즘을 찾고 있습니다. 나는 방금 하나를 쓰기 시작했고 그것이 지루한 일이 무엇인지 깨달았습니다. "어제", "마지막 주"와 "지난 달 말"의 차이와 같은 특별한 경우에 대처하기 위해 많은 끔찍한 코드로 빠르게 변성되었습니다. 오늘 날짜를 기준으로.

오픈 소스 퍼지 날짜 Formatter가 있어야한다고 생각하지만 찾을 수 없습니다. 이상적으로는 NSDate (OSX/iPhone)와 그 형태를 사용하는 것을 원하지만 어려운 것은 아닙니다. 누구든지 퍼지 날짜 형태를 알고있는 사람은 지금과 관련하여 시간을 내고 다음과 같은 문자열을 반환합니다.

  • 잠시 전에
  • 지난 5 분 안에
  • 오늘 일찍
  • 오늘 아침
  • 지난 밤
  • 지난주
  • 지난 수요일
  • 지난 달 초
  • 작년 6 월
  • 몇 년 전

이상적인 세상에서 나는 줄이 가능한 한 풍부하기를 원합니다 (즉, "그냥 지금"과 같은 "단지 한 순간"에 임의의 변형을 반환합니다).

설명. 나는 기본적인 벅트와 끈보다 더 미묘한 것을 찾고 있습니다. 나는 "어제"와 "마지막 수요일"을 아는 것을 원한다. 둘 다 같은 기간을 언급 할 수 있지만 오늘은 목요일이 될 때만 맞다.

도움이 되었습니까?

해결책

이 질문은 당신을 시작해야합니다. 이 사이트에서 상대 시간을 계산하는 데 사용하는 코드가 있습니다. 원하는 특정 범위가 없을 수도 있지만 설정 한 후에는 추가하기에 쉽습니다.

다른 팁

nsdateformatter에 속성이 있습니다 - "doSrelativedateformatting". 10.6/iOS4.0 이상으로 표시되지만 올바른 로케일에서 날짜를 상대 날짜로 형성합니다.

에서 애플의 문서:

Date Formatter가 상대 날짜 형식을 사용하는 경우, 가능한 경우 출력의 날짜 구성 요소를 "오늘"또는 "내일"과 같은 문구로 대체하여 상대 날짜를 나타냅니다. 사용 가능한 문구는 날짜 Formatter의 로케일에 따라 다릅니다. 미래의 날짜는 영어가“내일”만 허용 할 수 있지만 프랑스어는 다음 예에서 설명 된 것처럼“내일 다음 날 다음 날”을 허용 할 수 있습니다.

암호

다음은 주어진 로케일에 대해 상대적인 문자열을 많이 인쇄하는 코드입니다.

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

메모:

  • 로케일은 필요하지 않습니다
  • 영어를 대체하는 것은 많지 않습니다. 글을 쓰는 시점에는 "어제, 오늘, 내일"이 있습니다. 애플은 미래에 더 많은 것을 포함 할 수있다.
  • 로케일을 바꾸고 다른 언어로 제공되는 것을 보는 것은 재미 있습니다 (프랑스어는 영어보다 몇 가지가 더 많습니다.
  • iOS에있는 경우 구독 할 수 있습니다. UIAPPLICATIONIFICENTIFANTTIMECHANGENOTIFICE

인터페이스 빌더

인터페이스 빌더에서 "doSRelativedateFormatting"속성을 설정할 수 있습니다.

  • NSDateFormatter를 선택하고 검사관 팔레트의 "Identity Inspector"탭을 선택하십시오 (마지막 [명령 -6]).
  • "사용자 정의 런타임 속성"이라는 하위 섹션에서 선택한 개체에 대한 키에 대한 자체 값을 추가 할 수 있습니다 (이 경우 NSDateFormatter 인스턴스). "DoSRelativedateFormatting"을 추가하고 "부울"유형을 선택한 다음 확인했는지 확인하십시오.
  • 기억하다: 전혀 작동하지 않은 것처럼 보일 수 있지만 로케일에 대한 대체 값이 몇 개 밖에 없기 때문일 수 있습니다. 어제, 오늘, 내일의 날짜가 적어도 설정되지 않은지 결정하기 전에 날짜를 바르십시오.

레일을보고 싶을 수도 있습니다 distance_of_time_in_words 기능 date_helper.rb, 아래로 붙여 넣었습니다.

# 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

그래서 여기에 내가 여전히 관심이있는 사람들을 위해 NSDATE에 쓴 카테고리가 있습니다. 문제는 약간 quixotic이되는 문제 중 하나입니다. 기본적으로 거대한 스위치 문자입니다 (비록 내가 더 읽기 쉬운 일련의 계단식 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.
}

게시하는 데 너무 오래 걸려서 죄송합니다 ...

이것은 예쁘고 인도적인 날짜 및 시간 스레드의 코드를 기반으로합니다. 나는 X 며칠 전에 그것을 좋아하기 때문에 "지난 월요일 오후 5시"에 대한 핸들링을 추가했습니다. 이것은 수 세기까지 과거와 미래를 처리합니다. 나는 국제화 측면에 관심이 있으므로 결국 더 많은 작업이 필요합니다. 계산은 현지 시간대에 있습니다.

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

왜 당신이 그것이 끔찍한 코딩 연습이라고 말하는지 잘 모르겠습니다. 각 반환 문자열은 실제로 상위 세트의 하위 집합이므로 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"

내 경험상 이러한 유형의 날짜 생성기는 전혀 "퍼지"가 아닙니다. 실제로, 그것들은 단지 if 문장 기반의 시간 대역 일뿐입니다. 예를 들어, 30 초 미만의 시간은 "순간 전", 360 ~ 390 일은 "1 년 전"입니다. 이들 중 일부는 대상 날짜를 사용하여 특수 이름 (6 월, 수요일 등)을 계산합니다. 당신이 가진 환상을 돌려서 죄송합니다.

말할 것도없이 (그러나 어쨌든 말할 것입니다) 366 일 약시 연도에도 연간 365 일을 줄이는 Where 루프를 사용하지 마십시오 (또는 Zune 개발자의 순위에서 자신을 찾을 수 있습니다).

AC# 버전은 다음과 같습니다.

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

나는 이와 같은 시간이 최근에 인기를 얻었음을 알고 있지만, 전환하는 옵션을 상대적으로 '퍼지'날짜와 정상적인 절대 날짜로 만드는 것을 고려하십시오.

예를 들어, 5 분 전에 의견이 작성되었다는 사실을 아는 것이 유용하지만, 4 시간 전 A라는 의견을 말하는 것은 유용하지 않습니다. 댓글 B는 9 시간 전 오전 11시에 댓글을 달았습니다. 누군가 오늘 아침에 일어 났을 때 글을 쓰고 댓글 B는 늦게까지 머무르는 누군가에 의해 작성되었습니다 (내가 시간대에 있다는 것을 알고 있다고 가정).

- 편집 : 질문을 자세히 살펴보면 "X AGO"대신 시간을 언급하여 어느 정도 피하는 것처럼 보이지만 반면에 사용자가 다른 시간 내에있는 경우 잘못된 인상을 줄 수 있습니다. "오늘 아침"이 관련 사용자의 한밤중에있을 수 있기 때문에 구역.

다른 사용자의 시간대에 따라 상대적인 시간으로 시간을 확대하는 것이 시원 할 수 있지만, 사용자가 기꺼이 공급하고 정확하다고 가정합니다.

나는 다른 질문의 해결책에 만족하지 않았습니다. 그래서 날짜 시간 수업을 사용하여 나만의 것을 만들었습니다. 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";
}

이것은 거의 항상 거대한 스위치 명세서를 사용하여 수행되며 구현하기가 사소합니다.

다음을 명심하십시오.

  • 항상 가장 작은 시간을 먼저 테스트하십시오
  • 문자열을 현지화 할 수있는 것을 잊지 마십시오.

당신은 찾을 수 있습니다 Timeago의 출처 유용한. 플러그인에 대한 설명은 "퍼지 타임 스탬프 (예 : 4 분 전"또는 "약 1 일 전")를 자동으로 업데이트 할 수있는 jQuery 플러그인입니다.

본질적으로 Rail의 JavaScript 포트입니다 distance_of_time_in_words jQuery 플러그인에 기능이 쇄도합니다.

우리 회사는 가지고 있습니다 이 .NET 라이브러리 그것은 당신이 원하는 것 중 일부를 매우 유연한 날짜 시간 구문 분석 (일부 상대 형식 포함)을 수행하지만 비 관계형 출력 만 수행합니다.

JavaScript 휴리스틱 날짜 구문 프로그램은 Chrono를 확인하십시오.

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

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top