42

我想将 nsdate 转换为相对格式,例如"Today","Yesterday","a week ago","a month ago","a year ago","date as it is".

我已经为它写了下面的方法..但是一些它是如何打印的,因为它是日期..你能告诉我应该是什么问题吗?

//以下是将日期转换为相对字符串的函数

+(NSString *)getDateDiffrence:(NSDate *)strDate{
    NSDateFormatter *df = [[NSDateFormatter alloc] init];

    df.timeStyle = NSDateFormatterMediumStyle;
    df.dateStyle = NSDateFormatterShortStyle;
    df.doesRelativeDateFormatting = YES;
    NSLog(@"STRING DATEEE : %@ REAL DATE TODAY %@",[df stringFromDate:strDate],[NSDate date]);
      return [df stringFromDate:strDate];

}

我有以下格式的日期字符串"2013-10-29T09:38:00"

当我试图给 NSDate 对象时,它总是返回空日期。
所以我尝试将该日期转换为yyyy-MM-dd HH:mm:ssZZZZ然后我将这个日期传递给函数然后它只是打印整个日期..

如何解决这个问题呢?

//下面是我调用上面函数的代码

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss"];
NSDate *date = [formatter dateFromString:[threadDict objectForKey:@"lastMessageDate"]];
[formatter setDateFormat:@"yyyy-MM-dd HH:mm:ssZZZZ"];

NSString *date1 = [formatter stringFromDate:date];
NSDate *date_d = [formatter dateFromString:date1];
NSString *resultstr=[UserManager getDateDiffrence:date];

self.dateLabel.text=resultstr;
4

16 回答 16

57

为简单起见,我假设您正在格式化的日期都是过去的(没有“明天”或“下周”)。不是不能做,而是需要处理更多的案例,返回更多的字符串。


您可以使用components:fromDate:toDate:options:您正在寻找的任何日期组件组合来获取两个日期之间的年数、月数、周数、天数、小时数等。然后按照从最重要(例如年份)到最不重要(例如天)的顺序遍历它们,您可以仅根据最重要的组件格式化字符串。

例如:1 周 2 天 7 小时前的日期将被格式化为“1 周”。

如果您想为一个特殊数字的单位创建特殊字符串,例如“明天”代表“1 天前”,那么您可以在确定该组件是最重要的组件后检查该组件的值。

代码看起来像这样:

- (NSString *)relativeDateStringForDate:(NSDate *)date
{
    NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitWeekOfYear | 
                           NSCalendarUnitMonth | NSCalendarUnitYear;

    // if `date` is before "now" (i.e. in the past) then the components will be positive
    NSDateComponents *components = [[NSCalendar currentCalendar] components:units
                                                                   fromDate:date
                                                                     toDate:[NSDate date]
                                                                    options:0];

    if (components.year > 0) {
        return [NSString stringWithFormat:@"%ld years ago", (long)components.year];
    } else if (components.month > 0) {
        return [NSString stringWithFormat:@"%ld months ago", (long)components.month];
    } else if (components.weekOfYear > 0) {
        return [NSString stringWithFormat:@"%ld weeks ago", (long)components.weekOfYear];
    } else if (components.day > 0) {
        if (components.day > 1) {
            return [NSString stringWithFormat:@"%ld days ago", (long)components.day];
        } else {
            return @"Yesterday";
        }
    } else {
        return @"Today";
    }
}

如果您的日期也可能在未来,那么您可以以相同的顺序检查组件的绝对值,然后检查它是正数还是负数以返回适当的字符串。我只显示下面的年份:

if ( abs(components.year > 0) ) { 
    // year is most significant component
    if (components.year > 0) {
        // in the past
        return [NSString stringWithFormat:@"%ld years ago", (long)components.year];
    } else {
        // in the future
        return [NSString stringWithFormat:@"In %ld years", (long)components.year];
    }
} 
于 2013-12-10T07:41:59.980 回答
19

请注意,从 iOS 13 开始,现在有了RelativeDateTimeFormatter可以为您完成大部分工作!WWDC 2019 视频在这里。

let formatter = RelativeDateTimeFormatter()
let dateString = formatter.localizedString(for: aDate, relativeTo: now)

// en_US: "2 weeks ago"
// es_ES: "hace 2 semanas"
// zh_TW: "2 週前"

我已将我之前的答案留在下面以供后代使用。干杯!

⚠️ 您需要通读前面的答案,了解一些避免某些错误的关键提示。提示:在比较不是今天的日期时,使用当天日期/时间的结束作为相对日期!


这是我的答案(在Swift 3中!)以及为什么它更好。

回答:

func datePhraseRelativeToToday(from date: Date) -> String {

    // Don't use the current date/time. Use the end of the current day 
    // (technically 0h00 the next day). Apple's calculation of 
    // doesRelativeDateFormatting niavely depends on this start date.
    guard let todayEnd = dateEndOfToday() else {
        return ""
    }

    let calendar = Calendar.autoupdatingCurrent

    let units = Set([Calendar.Component.year,
                 Calendar.Component.month,
                 Calendar.Component.weekOfMonth,
                 Calendar.Component.day])

    let difference = calendar.dateComponents(units, from: date, to: todayEnd)

    guard let year = difference.year,
        let month = difference.month,
        let week = difference.weekOfMonth,
        let day = difference.day else {
            return ""
    }

    let timeAgo = NSLocalizedString("%@ ago", comment: "x days ago")

    let dateFormatter: DateFormatter = {
        let formatter = DateFormatter()
        formatter.locale = Locale.autoupdatingCurrent
        formatter.dateStyle = .medium
        formatter.doesRelativeDateFormatting = true
        return formatter
    }()

    if year > 0 {
        // sample output: "Jan 23, 2014"
        return dateFormatter.string(from: date)
    } else if month > 0 {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .brief // sample output: "1mth"
        formatter.allowedUnits = .month
        guard let timePhrase = formatter.string(from: difference) else {
            return ""
        }
        return String(format: timeAgo, timePhrase)
    } else if week > 0 {
        let formatter = DateComponentsFormatter()
        formatter.unitsStyle = .brief; // sample output: "2wks"
        formatter.allowedUnits = .weekOfMonth
        guard let timePhrase = formatter.string(from: difference) else {
            return ""
        }
        return String(format: timeAgo, timePhrase)
    } else if day > 1 {
            let formatter = DateComponentsFormatter()
            formatter.unitsStyle = .abbreviated; // sample output: "3d"
            formatter.allowedUnits = .day
            guard let timePhrase = formatter.string(from: difference) else {
                return ""
            }
            return String(format: timeAgo, timePhrase)
    } else {
        // sample output: "Yesterday" or "Today"
        return dateFormatter.string(from: date)
    }
}

func dateEndOfToday() -> Date? {
    let calendar = Calendar.autoupdatingCurrent
    let now = Date()
    let todayStart = calendar.startOfDay(for: now)
    var components = DateComponents()
    components.day = 1
    let todayEnd = calendar.date(byAdding: components, to: todayStart)
    return todayEnd
}

请记住重用您的格式化程序以避免任何性能损失!提示:对 DateFormatter 和 DateComponentsFormatter 的扩展是个好主意。

为什么更好:

  • 利用 DateFormatter 的“昨天”和“今天”。这已经由 Apple 翻译,可以节省您的工作量!
  • 使用 DateComponentsFormatter 已经翻译的“1 周”字符串。(再次为您减少工作量,由 Apple 提供。)您所要做的就是翻译“%@ ago”字符串。
  • 其他答案错误地计算了一天从“今天”切换到“昨天”到等的时间。固定常数是一个很大的 NO-NO,因为原因。此外,其他答案应使用当前日期/时间的结束时使用当前日期/时间。
  • 对日历和区域设置使用 autoupdatingCurrent,确保您的应用立即与 Settings.app 中用户的日历和语言首选项保持同步

这个答案的灵感来自 GitHub 上的DateTools

于 2016-12-21T20:45:11.297 回答
10

Swift 更新,感谢 David Rönnqvist 的 Objective-c 回答,它将适用于过去的日期。

func relativeDateStringForDate(date : NSDate) -> NSString {

        let todayDate = NSDate()
        let units: NSCalendarUnit = [.Hour, .Day, .Month, .Year, .WeekOfYear]
        let components = NSCalendar.currentCalendar().components(units, fromDate: date , toDate: todayDate, options: NSCalendarOptions.MatchFirst )

        let year =  components.year
        let month = components.month
        let day = components.day
        let hour = components.hour
        let weeks = components.weekOfYear
        // if `date` is before "now" (i.e. in the past) then the components will be positive

        if components.year > 0 {
            return NSString.init(format: "%d years ago", year);
        } else if components.month > 0 {
            return NSString.init(format: "%d months ago", month);
        } else if components.weekOfYear > 0 {
            return NSString.init(format: "%d weeks ago", weeks);
        } else if (components.day > 0) {
            if components.day > 1 {
                return NSString.init(format: "%d days ago", day);
            } else {
                return "Yesterday";
            }
        } else {
            return NSString.init(format: "%d hours ago", hour);
        }
    }
于 2016-04-20T19:27:09.947 回答
9

适用于:斯威夫特 3

这是过去日期的 Swift 3 版本,它处理返回的字符串中的所有单位和单数或复数。

使用示例:

let oneWeekAgo = Calendar.current.date(byAdding: .weekOfYear, value: -1, to: Date())!

print(relativePast(for: oneWeekAgo)) // output: "1 week ago"

我基于 Saurabh Yadav 的即兴演奏。谢谢。

func relativePast(for date : Date) -> String {

    let units = Set<Calendar.Component>([.year, .month, .day, .hour, .minute, .second, .weekOfYear])
    let components = Calendar.current.dateComponents(units, from: date, to: Date())

    if components.year! > 0 {
        return "\(components.year!) " + (components.year! > 1 ? "years ago" : "year ago")

    } else if components.month! > 0 {
        return "\(components.month!) " + (components.month! > 1 ? "months ago" : "month ago")

    } else if components.weekOfYear! > 0 {
        return "\(components.weekOfYear!) " + (components.weekOfYear! > 1 ? "weeks ago" : "week ago")

    } else if (components.day! > 0) {
        return (components.day! > 1 ? "\(components.day!) days ago" : "Yesterday")

    } else if components.hour! > 0 {
        return "\(components.hour!) " + (components.hour! > 1 ? "hours ago" : "hour ago")

    } else if components.minute! > 0 {
        return "\(components.minute!) " + (components.minute! > 1 ? "minutes ago" : "minute ago")

    } else {
        return "\(components.second!) " + (components.second! > 1 ? "seconds ago" : "second ago")
    }
}
于 2016-10-18T20:27:42.140 回答
7

为了避免 Budidino 对大卫的回答提到的 24 小时问题,我将其更改为如下所示 -

- (NSString *)relativeDateStringForDate:(NSDate *)date
{

NSCalendarUnit units = NSDayCalendarUnit | NSWeekOfYearCalendarUnit |
NSMonthCalendarUnit | NSYearCalendarUnit ;
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateComponents *components1 = [cal components:(NSCalendarUnitEra|NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay) fromDate:[NSDate date]];
NSDate *today = [cal dateFromComponents:components1];

components1 = [cal components:(NSCalendarUnitEra|NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay) fromDate:date];
NSDate *thatdate = [cal dateFromComponents:components1];

// if `date` is before "now" (i.e. in the past) then the components will be positive
NSDateComponents *components = [[NSCalendar currentCalendar] components:units
                                                               fromDate:thatdate
                                                                 toDate:today
                                                                options:0];

if (components.year > 0) {
    return [NSString stringWithFormat:@"%ld years ago", (long)components.year];
} else if (components.month > 0) {
    return [NSString stringWithFormat:@"%ld months ago", (long)components.month];
} else if (components.weekOfYear > 0) {
    return [NSString stringWithFormat:@"%ld weeks ago", (long)components.weekOfYear];
} else if (components.day > 0) {
    if (components.day > 1) {
        return [NSString stringWithFormat:@"%ld days ago", (long)components.day];
    } else {
        return @"Yesterday";
    }
} else {
    return @"Today";
}
}

基本上,它会创建 2 个不包括时间段的新日期。然后比较“天”的差异。

于 2015-04-29T11:23:49.370 回答
4

check NSDate-TimeAgo, it also supports multiple languages.

于 2013-12-10T08:14:08.587 回答
3

你需要自己解决这个逻辑。您需要确定这两个日期之间的天数。

这是一个相对幼稚的方法:

+ (NSString *) dateDifference:(NSDate *)date
{
    const NSTimeInterval secondsPerDay = 60 * 60 * 24;
    NSTimeInterval diff = [date timeIntervalSinceNow] * -1.0;

    // if the difference is negative, then the given date/time is in the future
    // (because we multiplied by -1.0 to make it easier to follow later)
    if (diff < 0)
        return @"In the future";

    diff /= secondsPerDay; // get the number of days

    // if the difference is less than 1, the date occurred today, etc.
    if (diff < 1)
        return @"Today";
    else if (diff < 2)
        return @"Yesterday";
    else if (diff < 8)
        return @"Last week";
    else
        return [date description]; // use a date formatter if necessary
}

这很天真,原因有很多:

  1. 它没有考虑闰日
  2. 它假设一天有 86400 秒(有闰秒之类的东西!)

但是,这至少应该可以帮助您朝着正确的方向前进。另外,避免get在方法名称中使用。在方法名称中使用get通常表示调用者必须提供自己的输出缓冲区。考虑NSArray的方法,getItems:range:NSString的方法,getCharacters:range:

于 2013-12-10T06:33:29.340 回答
3
NSString* AgoStringFromTime(NSDate* dateTime)
{
    NSDictionary *timeScale = @{@"sec"  :@1,
                                @"min"  :@60,
                                @"hr"   :@3600,
                                @"day"  :@86400,
                                @"week" :@605800,
                                @"month":@2629743,
                                @"year" :@31556926};
    NSString *scale;
    int timeAgo = 0-(int)[dateTime timeIntervalSinceNow];
    if (timeAgo < 60) {
        scale = @"sec";
    } else if (timeAgo < 3600) {
        scale = @"min";
    } else if (timeAgo < 86400) {
        scale = @"hr";
    } else if (timeAgo < 605800) {
        scale = @"day";
    } else if (timeAgo < 2629743) {
        scale = @"week";
    } else if (timeAgo < 31556926) {
        scale = @"month";
    } else {
        scale = @"year";
    }

    timeAgo = timeAgo/[[timeScale objectForKey:scale] integerValue];
    NSString *s = @"";
    if (timeAgo > 1) {
        s = @"s";
    }

    return [NSString stringWithFormat:@"%d %@%@", timeAgo, scale, s];
}
于 2014-09-02T11:04:15.697 回答
2

这是我为自己使用而创建的代码:

+ (NSString*) getTimestampForDate:(NSDate*)date {

    NSDate* sourceDate = date;

    // Timezone Offset compensation (optional, if your target users are limited to a single time zone.)

    NSTimeZone* sourceTimeZone = [NSTimeZone timeZoneWithName:@"America/New_York"];
    NSTimeZone* destinationTimeZone = [NSTimeZone systemTimeZone];

    NSInteger sourceGMTOffset = [sourceTimeZone secondsFromGMTForDate:sourceDate];
    NSInteger destinationGMTOffset = [destinationTimeZone secondsFromGMTForDate:sourceDate];

    NSTimeInterval interval = destinationGMTOffset - sourceGMTOffset;

    NSDate* destinationDate = [[NSDate alloc] initWithTimeInterval:interval sinceDate:sourceDate];

    // Timestamp calculation (based on compensation)

    NSCalendar* currentCalendar = [NSCalendar currentCalendar];
    NSCalendarUnit unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit;

    NSDateComponents *differenceComponents = [currentCalendar components:unitFlags fromDate:destinationDate toDate:[NSDate date] options:0];//Use `date` instead of `destinationDate` if you are not using Timezone offset correction

    NSInteger yearDifference = [differenceComponents year];
    NSInteger monthDifference = [differenceComponents month];
    NSInteger dayDifference = [differenceComponents day];
    NSInteger hourDifference = [differenceComponents hour];
    NSInteger minuteDifference = [differenceComponents minute];

    NSString* timestamp;

    if (yearDifference == 0
        && monthDifference == 0
        && dayDifference == 0
        && hourDifference == 0
        && minuteDifference <= 2) {

        //"Just Now"

        timestamp = @"Just Now";

    } else if (yearDifference == 0
               && monthDifference == 0
               && dayDifference == 0
               && hourDifference == 0
               && minuteDifference < 60) {

        //"13 minutes ago"

        timestamp = [NSString stringWithFormat:@"%ld minutes ago", (long)minuteDifference];

    } else if (yearDifference == 0
               && monthDifference == 0
               && dayDifference == 0
               && hourDifference == 1) {

        //"1 hour ago" EXACT

        timestamp = @"1 hour ago";

    } else if (yearDifference == 0
               && monthDifference == 0
               && dayDifference == 0
               && hourDifference < 24) {

        timestamp = [NSString stringWithFormat:@"%ld hours ago", (long)hourDifference];

    } else {

        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
        [formatter setLocale:[NSLocale currentLocale]];

        NSString* strDate, *strDate2 = @"";

        if (yearDifference == 0
            && monthDifference == 0
            && dayDifference == 1) {

            //"Yesterday at 10:23 AM", "Yesterday at 5:08 PM"

            [formatter setDateFormat:@"hh:mm a"];
            strDate = [formatter stringFromDate:date];

            timestamp = [NSString stringWithFormat:@"Yesterday at %@", strDate];

        } else if (yearDifference == 0
                   && monthDifference == 0
                   && dayDifference < 7) {

            //"Tuesday at 7:13 PM"

            [formatter setDateFormat:@"EEEE"];
            strDate = [formatter stringFromDate:date];
            [formatter setDateFormat:@"hh:mm a"];
            strDate2 = [formatter stringFromDate:date];

            timestamp = [NSString stringWithFormat:@"%@ at %@", strDate, strDate2];

        } else if (yearDifference == 0) {

            //"July 4 at 7:36 AM"

            [formatter setDateFormat:@"MMMM d"];
            strDate = [formatter stringFromDate:date];
            [formatter setDateFormat:@"hh:mm a"];
            strDate2 = [formatter stringFromDate:date];

            timestamp = [NSString stringWithFormat:@"%@ at %@", strDate, strDate2];

        } else {

            //"March 24 2010 at 4:50 AM"

            [formatter setDateFormat:@"d MMMM yyyy"];
            strDate = [formatter stringFromDate:date];
            [formatter setDateFormat:@"hh:mm a"];
            strDate2 = [formatter stringFromDate:date];

            timestamp = [NSString stringWithFormat:@"%@ at %@", strDate, strDate2];
        }
    }

    return timestamp;
}
于 2013-12-10T08:02:05.250 回答
2

这只是先前答案的副本,但Just now如果少于五秒,它会返回。

func relativePast(for date : Date) -> String {

    let units = Set<Calendar.Component>([.year, .month, .day, .hour, .minute, .second, .weekOfYear])
    let components = Calendar.current.dateComponents(units, from: date, to: Date())

    if components.year! > 0 {
        return "\(components.year!) " + (components.year! > 1 ? "years ago" : "year ago")

    } else if components.month! > 0 {
        return "\(components.month!) " + (components.month! > 1 ? "months ago" : "month ago")

    } else if components.weekOfYear! > 0 {
        return "\(components.weekOfYear!) " + (components.weekOfYear! > 1 ? "weeks ago" : "week ago")

    } else if (components.day! > 0) {
        return (components.day! > 1 ? "\(components.day!) days ago" : "Yesterday")

    } else if components.hour! > 0 {
        return "\(components.hour!) " + (components.hour! > 1 ? "hours ago" : "hour ago")

    } else if components.minute! > 0 {
        return "\(components.minute!) " + (components.minute! > 1 ? "minutes ago" : "minute ago")

    } else {
        return "\(components.second!) " + (components.second! > 5 ? "seconds ago" : "Just Now".replacingOccurrences(of: "0", with: "")
    }
}
于 2017-07-29T10:48:49.083 回答
1

问题doesRelativeDateFormatting在于它几乎仅限于Yesterday, Today, Tomorrow. 如果您正在寻找更彻底的内容,请查看此处的答案

于 2013-12-10T06:33:51.193 回答
1

这是我在 Swift 2 中的解决方案,它通过将两个日期与零时间进行比较来避免 24 小时问题。

extension NSDate {

private func dateWithZeroTime(date: NSDate) -> NSDate? {
    let calendar = NSCalendar.currentCalendar()
    let units: NSCalendarUnit = [.Day, .WeekOfYear, .Month, .Year]
    let components = calendar.components(units, fromDate: date)
    return calendar.dateFromComponents(components)
}

private func thisDay() -> NSDate? {
    return self.dateWithZeroTime(self)
}

private func today() -> NSDate? {
    return self.dateWithZeroTime(NSDate())
}

var relativeFormat: String? {
    let today = self.today()
    let thisDay = self.thisDay()
    
    let formatter = NSDateFormatter()
    formatter.dateStyle = NSDateFormatterStyle.LongStyle
    let dateString = formatter.stringFromDate(self)
    
    if nil != thisDay && nil != today {
        let units: NSCalendarUnit = [.Day, .WeekOfYear, .Month, .Year]
        let components = NSCalendar.currentCalendar().components(units, fromDate: thisDay!, toDate: today!, options: [])
        
        if (components.year > 0) {
            return components.year == 1 ? "A year ago, \(dateString)" : "\(components.year) years ago, \(dateString)"
        } else if (components.month > 0) {
            return components.month == 1 ? "A month ago, \(dateString)" : "\(components.month) months ago, \(dateString)"
        } else if (components.weekOfYear > 0) {
            return components.weekOfYear == 1 ? "A week ago, \(dateString)" : "\(components.weekOfYear) weeks ago, \(dateString)"
        } else if (components.day > 0) {
            return components.day == 1 ? "Yesterday, \(dateString)" : "\(self.dayOfTheWeek()), \(dateString)"
        } else {
            return "Today"
        }
    }
    
    return nil
}

func dayOfTheWeek() -> String {
    let weekdays = [
        "Sunday",
        "Monday",
        "Tuesday",
        "Wednesday",
        "Thursday",
        "Friday",
        "Saturday"
    ]
    
    let calendar: NSCalendar = NSCalendar.currentCalendar()
    let components: NSDateComponents = calendar.components(.Weekday, fromDate: self)
    return weekdays[components.weekday - 1]
}
}

Swift 5 解决方案:

public extension Date {

  private func dateWithZeroTime(_ date: Date) -> Date? {
    let calendar = Calendar.current
    let units: Set<Calendar.Component> = Set( [.day, .weekOfYear, .month, .year])
    let components = calendar.dateComponents(units, from: date)
    return calendar.date(from: components)
  }

  private func thisDay() -> Date? {
    return self.dateWithZeroTime(self)
  }

  private func today() -> Date? {
    return self.dateWithZeroTime(Date())
  }

  var relativeFormat: String? {
    let formatter = DateFormatter()
    formatter.dateStyle = DateFormatter.Style.long
    let dateString = formatter.string(from: self)

    if let thisDay = self.thisDay(),
       let today = self.today() {
      let units: Set<Calendar.Component> = Set([.day, .weekOfYear, .month, .year])
      let components = Calendar.current.dateComponents(units, from: thisDay, to: today)
  
      if let year = components.year,
         year > 0 {
        return year == 1 ? "A year ago, \(dateString)" : "\(year) years ago, \(dateString)"
      } else if let month = components.month,
                month > 0 {
        return month == 1 ? "A month ago, \(dateString)" : "\(month) months ago, \(dateString)"
      } else if let weekOfYear = components.weekOfYear,
                weekOfYear > 0 {
        return weekOfYear == 1 ? "A week ago, \(dateString)" : "\(weekOfYear) weeks ago, \(dateString)"
      } else if let day = components.day,
                day > 0 {
        return day == 1 ? "Yesterday, \(dateString)" : dayOfWeekWithDateString(dateString)
      } else {
        return "Today"
      }
    }

    return nil
  }

  func dayOfTheWeek() -> String? {
    let weekdays = [
      "Sunday",
      "Monday",
      "Tuesday",
      "Wednesday",
      "Thursday",
      "Friday",
      "Saturday"
    ]

    let calendar = Calendar.current
    let components: DateComponents = calendar.dateComponents(Set([.weekday]), from: self)

    guard let weekday = components.weekday else { return nil }

    return weekdays[weekday - 1]
  }

  func dayOfWeekWithDateString(_ dateString: String) -> String {
    if let dayOfWeek = dayOfTheWeek() {
      return "\(dayOfWeek), \(dateString)"
    } else {
      return dateString
    }
  }
}
于 2017-02-17T14:41:27.977 回答
1

我已在此处附加演示,请在此链接上找到。TimestampAgo-Demo

感谢n00bprogrammer

编辑:-我使用 [NSTimeZone systemTimeZone] 在 Sourcetimezone 中进行了更改,因为由于静态时区,问题出现在 GMT 或 UTC 格式。(第二个减号)并更改不推荐使用的方法。

于 2016-07-22T08:17:12.450 回答
1

如果期货日期,请填写代码

NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitWeekOfYear | 
                           NSCalendarUnitMonth | NSCalendarUnitYear;


    NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate:date toDate:[NSDate date] options:0];

    if (components.year < 0) {
            return [NSString stringWithFormat:@"%ld years from now", labs((long)components.year)];
        } else if (components.month < 0) {
            return [NSString stringWithFormat:@"%ld months from now", labs((long)components.month)];
        } else if (components.weekOfYear < 0) {
            return [NSString stringWithFormat:@"%ld weeks from now", labs((long)components.weekOfYear)];
        } else if (components.day < 0) {
            if (components.day < 1) {
                return [NSString stringWithFormat:@"%ld days from now", labs((long)components.day)];
            } else {
                return @"Tomorrow";
            }
        }
        else if (components.year > 0) {
            return [NSString stringWithFormat:@"%ld years ago", (long)components.year];
        } else if (components.month > 0) {
            return [NSString stringWithFormat:@"%ld months ago", (long)components.month];
        } else if (components.weekOfYear > 0) {
            return [NSString stringWithFormat:@"%ld weeks ago", (long)components.weekOfYear];
        } else if (components.day > 0) {
            if (components.day > 1) {
                return [NSString stringWithFormat:@"%ld days ago", (long)components.day];
            } else {
                return @"Yesterday";
            }
        } else {
            return @"Today";
        }
于 2015-12-28T13:51:41.020 回答
0

要将给定的“sourceDate”格式化为今天的“5:56 pm”,昨天的任何时间“yesterday”,同年任何一天的“January 16”和“2014 年 1 月 16 日”。我正在发布我自己的方法。

sourceDate = //some date that you need to take into consideration


 NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate:[NSDate date]];
    NSDateComponents *sourceDateComponents = [[NSCalendar currentCalendar] components:NSCalendarUnitMinute | NSCalendarUnitHour | NSCalendarUnitDay | NSCalendarUnitMonth | NSCalendarUnitYear fromDate: sourceDate];

    NSString* timestamp;

    NSDateFormatter *formatSourceDate   =   [NSDateFormatter new];
    [formatSourceDate setAMSymbol:@"AM"];
    [formatSourceDate setPMSymbol:@"PM"];

    //same day - time in h:mm am/pm
    if (components.day == sourceDateComponents.day) {
        NSLogInfo(@"time");
        [formatSourceDate setDateFormat:@"h:mm a"];
        timestamp = [NSString stringWithFormat:@"%@",[formatSourceDate stringFromDate:date]];
        return timestamp;
    }
    else if (components.day - sourceDateComponents.day == 1) {
        //yesterday
        timestamp = NSLocalizedString(@"Yesterday", nil);
        return timestamp;
    }
    if (components.year == sourceDateComponents.year) {
        //september 29, 5:56 pm
        [formatSourceDate setDateFormat:@"MMMM d"];
        timestamp = [NSString stringWithFormat:@"%@",[formatSourceDate stringFromDate:date]];
        return timestamp;
    }
    [formatSourceDate setDateFormat:@"MMMM d year"];
    timestamp = [NSString stringWithFormat:@"%@",[formatSourceDate stringFromDate:date]];
    return timestamp;

    NSLogInfo(@"Timestamp : %@",timestamp);
于 2015-01-17T03:59:25.043 回答
0
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full

let now = NSDate()


let dateMakerFormatter = DateFormatter()

dateMakerFormatter.dateFormat = "yyyy/MM/dd HH:mm:ss z"
let dateString = "2017-03-13 10:38:54 +0000"
let stPatricksDay = dateMakerFormatter.date(from: dateString)!


let calendar = NSCalendar.current



let components = calendar.dateComponents([.hour, .minute,.weekOfMonth,.day,.year,.month,.second], from: stPatricksDay, to: now as Date)



if components.year! > 0 {
    formatter.allowedUnits = .year
} else if components.month! > 0 {
    formatter.allowedUnits = .month
} else if components.weekOfMonth! > 0 {
    formatter.allowedUnits = .weekOfMonth
} else if components.day! > 0 {
    formatter.allowedUnits = .day
} else if components.hour! > 0 {
    formatter.allowedUnits = .hour
} else if components.minute! > 0 {
    formatter.allowedUnits = .minute
} else {
    formatter.allowedUnits = .second
}

let formatString = NSLocalizedString("%@ ago", comment: "Used to say how much time has passed. e.g. '2 hours ago'")

 let timeString = formatter.string(from: components)

String(format: formatString, timeString!)
于 2017-03-13T11:26:06.610 回答