【问题标题】:Fuzzy Date algorithm in Objective-CObjective-C 中的模糊日期算法
【发布时间】:2009-06-27 14:50:05
【问题描述】:

我想在 Objective-C for iPhone 中编写一个模糊日期方法来计算日期。这里有一个通俗的解释:

Calculate relative time in C#

但是它包含缺少的参数。这怎么能在 Objective-C 中使用?谢谢。

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

【问题讨论】:

    标签: iphone objective-c algorithm datetime


    【解决方案1】:

    日期在 Cocoa 中使用 NSDate 类表示。在NSDate 中实现了一个方便的方法来获得两个日期实例之间的增量(以秒为单位)timeIntervalSinceDate:。这是在 NSDate 实例上调用的,将另一个 NSDate 对象作为参数。它返回一个NSTimeInterval(这是一个双精度类型定义),它代表两个日期之间的秒数。

    鉴于此,将您上面给出的代码调整到 Objective-C/Cocoa 上下文将相当简单。由于NSDate 计算的增量以秒为单位,给定两个日期,您可以轻松地修改上面的代码:

    //Constants
    #define SECOND 1
    #define MINUTE (60 * SECOND)
    #define HOUR (60 * MINUTE)
    #define DAY (24 * HOUR)
    #define MONTH (30 * DAY)
    
    - (NSString*)timeIntervalWithStartDate:(NSDate*)d1 withEndDate:(NSDate*)d2
    {
        //Calculate the delta in seconds between the two dates
        NSTimeInterval delta = [d2 timeIntervalSinceDate:d1];
    
        if (delta < 1 * MINUTE)
        {
            return delta == 1 ? @"one second ago" : [NSString stringWithFormat:@"%d seconds ago", (int)delta];
        }
        if (delta < 2 * MINUTE)
        {
            return @"a minute ago";
        }
        if (delta < 45 * MINUTE)
        {
            int minutes = floor((double)delta/MINUTE);
            return [NSString stringWithFormat:@"%d minutes ago", minutes];
        }
        if (delta < 90 * MINUTE)
        {
            return @"an hour ago";
        }
        if (delta < 24 * HOUR)
        {
            int hours = floor((double)delta/HOUR);
            return [NSString stringWithFormat:@"%d hours ago", hours];
        }
        if (delta < 48 * HOUR)
        {
            return @"yesterday";
        }
        if (delta < 30 * DAY)
        {
            int days = floor((double)delta/DAY);
            return [NSString stringWithFormat:@"%d days ago", days];
        }
        if (delta < 12 * MONTH)
        {
            int months = floor((double)delta/MONTH);
            return months <= 1 ? @"one month ago" : [NSString stringWithFormat:@"%d months ago", months];
        }
        else
        {
            int years = floor((double)delta/MONTH/12.0);
            return years <= 1 ? @"one year ago" : [NSString stringWithFormat:@"%d years ago", years];
        }
    }
    

    然后将调用它,将开始和结束 NSDate 对象作为参数传递,并返回带有时间间隔的 NSString

    【讨论】:

    • 这个实现的唯一问题是它没有区分一天 24 小时和日历日。即如果我比较晚上 11:00 和凌晨 2:00,差异应该是“昨天”而不是“3 小时前”查看 NSCalendar 及其伴随的 NSDateComponents 类。
    【解决方案2】:

    您可以使用timeIntervalSinceDate: 方法获取两个NSDate 对象之间的增量。这将在几秒钟内为您提供增量。

    您可以通过除以适当的数量来计算分钟/小时/天/月/年。

    【讨论】:

      【解决方案3】:

      作为替代方案,您可以依靠可以从两个日期之间的差异中提取的日历组件来避免容易出错的日历算术:

      NSDate *nowDate =    [[NSDate alloc] init];
      NSDate *targetDate = nil; // some other date here of your choosing, obviously nil isn't going to get you very far
      
      NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
      NSUInteger unitFlags = NSMonthCalendarUnit | NSWeekCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit;
      NSDateComponents *components = [gregorian components:unitFlags
                                                  fromDate:dateTime
                                                    toDate:nowDate options:0];
      NSInteger months = [components month];
      NSInteger weeks = [components week];
      NSInteger days = [components day];
      NSInteger hours = [components hour];
      NSInteger minutes = [components minute];
      

      关键是单位标志的设置 - 这允许您设置您希望将日期/时间分解为哪些时间单位。如果您只想要小时数,您可以设置 NSHourCalendarUnit,随着日期之间的距离越来越远,该值将继续增加,因为没有更大的单位开始增加。

      一旦你有了你的组件,你就可以继续你选择的逻辑,也许通过修改@alex的条件流。

      这是我拼凑起来的:

      if (months > 1) {
          // Simple date/time
          if (weeks >3) {
              // Almost another month - fuzzy
              months++;
          }
          return [NSString stringWithFormat:@"%ld months ago", (long)months];
      }
      else if (months == 1) {
          if (weeks > 3) {
              months++;
              // Almost 2 months
              return [NSString stringWithFormat:@"%ld months ago", (long)months];
          }
          // approx 1 month
          return [NSString stringWithFormat:@"1 month ago"];
      }
      // Weeks
      else if (weeks > 1) {
          if (days > 6) {
              // Almost another month - fuzzy
              weeks++;
          }
          return [NSString stringWithFormat:@"%ld weeks ago", (long)weeks];
      }
      else if (weeks == 1 ||
               days > 6) {
          if (days > 6) {
              weeks++;
              // Almost 2 weeks
              return [NSString stringWithFormat:@"%ld weeks ago", (long)weeks];
          }
          return [NSString stringWithFormat:@"1 week ago"];
      }
      // Days
      else if (days > 1) {
          if (hours > 20) {
              days++;
          }
          return [NSString stringWithFormat:@"%ld days ago", (long)days];
      }
      else if (days == 1) {
          if (hours > 20) {
              days++;
              return [NSString stringWithFormat:@"%ld days ago", (long)days];
          }
          return [NSString stringWithFormat:@"1 day ago"];
      }
      // Hours
      else if (hours > 1) {
          if (minutes > 50) {
              hours++;
          }
          return [NSString stringWithFormat:@"%ld hours ago", (long)hours];
      }
      else if (hours == 1) {
          if (minutes > 50) {
              hours++;
              return [NSString stringWithFormat:@"%ld hours ago", (long)hours];
          }
          return [NSString stringWithFormat:@"1 hour ago"];
      }
      // Minutes
      else if (minutes > 1) {
          return [NSString stringWithFormat:@"%ld minutes ago", (long)minutes];
      }
      else if (minutes == 1) {
          return [NSString stringWithFormat:@"1 minute ago"];
      }
      else if (minutes < 1) {
          return [NSString stringWithFormat:@"Just now"];
      }
      

      【讨论】:

        【解决方案4】:
        猜你喜欢
        • 2010-10-23
        • 2021-04-26
        • 1970-01-01
        • 2011-06-02
        • 1970-01-01
        • 2016-07-16
        • 2020-03-02
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多