2

I'm building an app that requires me to show time and day i.e Sunday if the object was created prior to 24hrs etc. Just like Message and Mail app in iOS would show time for 24Hrs and than change it to show days like 'monday, tuesday..". I was looking if i can find any framework that does exactly like this or do i have to write a code for this?

vikingosegundo
  • 52,040
  • 14
  • 137
  • 178
DevCali
  • 398
  • 6
  • 20
  • i can't i just need to show it in a TableViewCell, just like Mail and Message apps in iOS – DevCali Jan 20 '14 at 18:45
  • Just use one of two possible date formats (`NSDateFormatter`) depending on how recent the date is. – rmaddy Jan 20 '14 at 18:46
  • @rmaddy i think your comment makes more sense. i have so far this code that gives me the time only. how can i use this time to know if it was prior to 24hrs and if yes, how do i get the days like Monday, tuesday? if you could please answer with with some example, that would be great. NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init]; [dateFormatter setDateFormat:@"HH:mm:ss"]; NSString *timeStampStr = [dateFormatter stringFromDate:someObj.timeStamp]; – DevCali Jan 20 '14 at 19:31

8 Answers8

6

Here's how to do it all natively with Swift 4 & 5:

extension Date {

    func formatRelativeString() -> String {
        let dateFormatter = DateFormatter()
        let calendar = Calendar(identifier: .gregorian)
        dateFormatter.doesRelativeDateFormatting = true

        if calendar.isDateInToday(self) {
            dateFormatter.timeStyle = .short
            dateFormatter.dateStyle = .none
        } else if calendar.isDateInYesterday(self){
            dateFormatter.timeStyle = .none
            dateFormatter.dateStyle = .medium
        } else if calendar.compare(Date(), to: self, toGranularity: .weekOfYear) == .orderedSame {
            let weekday = calendar.dateComponents([.weekday], from: self).weekday ?? 0
            return dateFormatter.weekdaySymbols[weekday-1]
        } else {
            dateFormatter.timeStyle = .none
            dateFormatter.dateStyle = .short
        }

        return dateFormatter.string(from: self)
    }
}
MQLN
  • 2,292
  • 2
  • 18
  • 33
3

I needed this too, so I wrote the following NSDate extension:

extension NSDate {

    func formattedRelativeString() -> String {
        let dateFormatter = NSDateFormatter()
        dateFormatter.doesRelativeDateFormatting = true

        if isToday() {
            dateFormatter.timeStyle = .ShortStyle
            dateFormatter.dateStyle = .NoStyle
        } else if isYesterday() {
            dateFormatter.timeStyle = .NoStyle
            dateFormatter.dateStyle = .MediumStyle
        } else if daysAgo() < 6 {
            return dateFormatter.weekdaySymbols[weekday()-1]
        } else {
            dateFormatter.timeStyle = .NoStyle
            dateFormatter.dateStyle = .ShortStyle
        }

        return dateFormatter.stringFromDate(self)
    }
}

This requires Matthew York's excellent DateTools to work.

avf
  • 858
  • 11
  • 24
2

Swift 3 version of @avf response:

extension NSDate {
    func formattedRelativeString() -> String 
    {
        let dateFormatter = DateFormatter()
        dateFormatter.doesRelativeDateFormatting = true

        if isToday() {
            dateFormatter.timeStyle = .short
            dateFormatter.dateStyle = .none
        } else if isYesterday() {
            dateFormatter.timeStyle = .none
            dateFormatter.dateStyle = .medium
        } else if daysAgo() < 6 {
            return dateFormatter.weekdaySymbols[weekday()-1]
        } else {
            dateFormatter.timeStyle = .none
            dateFormatter.dateStyle = .short
        }

        return dateFormatter.string(from: self as Date)
    }
}
Community
  • 1
  • 1
Den Telezhkin
  • 633
  • 6
  • 9
2

updated for swift 4:

 extension NSDate {

    func formattedRelativeString() -> String 
    {
        let dateFormatter = DateFormatter()

        if isInToday || isInYesterday {
            /// today and yesterday
            /// Today, 3:57 PM
            dateFormatter.doesRelativeDateFormatting = true
            dateFormatter.timeStyle = .short
            dateFormatter.dateStyle = .short
        } else if isLessThanAweekAgo {

            /// less than a week ago
            /// Friday, 4:03 PM
            dateFormatter.dateFormat = "EEEE, h:mm a"
         } else if isInThisYear {

            // more than a week ago
            // Fri, 4 Aug, 3:55
            dateFormatter.dateFormat = "E, d MMM, h:mm a"
         } else {
            // more than a year ago
            // Aug 10, 2016, 3:56
            dateFormatter.dateFormat = "MMM d, yyyy, h:mm a"
         }

        return dateFormatter.string(from: self)
    }

}

you can test it in playground with these sample dates:

let now = Date()
let yesterday = Date(timeInterval: -24*60*60, since: Date())
let weekAgo = Date(timeInterval: -7*24*60*60, since: Date())
let yearAgo = Date(timeInterval: -366*24*60*60, since: Date())
Hashem Aboonajmi
  • 13,077
  • 8
  • 66
  • 75
0
NSString *dateString = [NSDateFormatter localizedStringFromDate:[NSDate date]
                                                              dateStyle:NSDateFormatterShortStyle
                                                              timeStyle:NSDateFormatterFullStyle];
        NSLog(@"%@",dateString);

Try this code, modify it as per your requirement.

Saad Chaudhry
  • 1,392
  • 23
  • 37
0

Objective C formating date and time.

Using Matthew York's excellent DateTools methods.

NSDate extension:

-(NSString *)formatDateTimeToString{
    NSDateFormatter* dateFormatter = [[NSDateFormatter alloc]init];
    [dateFormatter setLocale: [[NSLocale alloc] initWithLocaleIdentifier: [[NSLocale currentLocale] localeIdentifier]]];

    if ([[NSCalendar currentCalendar] isDateInToday:self])
    {
        [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
        [dateFormatter setDateStyle:NSDateFormatterNoStyle];
    }
    else if ([[NSCalendar currentCalendar] isDateInYesterday:self])
    {
        [dateFormatter setDoesRelativeDateFormatting:YES];
        [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
        [dateFormatter setDateStyle:NSDateFormatterMediumStyle];
    }
    else if ([self daysAgo]<6)
    {
        [dateFormatter setDateFormat:@"EEEE"];
    }
    else
    {
        [dateFormatter setTimeStyle:NSDateFormatterNoStyle];
        [dateFormatter setDateStyle:NSDateFormatterShortStyle];
    }
    return  [dateFormatter stringFromDate:self];
}


-(NSInteger)daysAgo{
    return [self daysEarlierThan:[NSDate date]];
}

-(NSInteger)daysEarlierThan:(NSDate *)date{
    return ABS(MIN([self daysFrom:date], 0));
}
-(NSInteger)daysFrom:(NSDate *)date{
    return [self daysFrom:date calendar:nil];
}
-(NSInteger)daysFrom:(NSDate *)date calendar:(NSCalendar *)calendar{
    NSDate *earliest = [self earlierDate:date];
    NSDate *latest = (earliest == self) ? date : self;
    NSInteger multiplier = (earliest == self) ? -1 : 1;
    NSDateComponents *components = [[NSCalendar currentCalendar] components:NSCalendarUnitDay fromDate:earliest toDate:latest options:0];
    return multiplier*components.day;
}
Alino
  • 153
  • 1
  • 9
0

I have tried all the above solutions but unfortunately, nothing worked for me. Anyway, I ended up with a solution.

Swift version

extension Date {

    func isEqual(to date: Date, toGranularity component: Calendar.Component, in calendar: Calendar = .current) -> Bool {
        calendar.isDate(self, equalTo: date, toGranularity: component)
    }

    func isInSameYear(as date: Date) -> Bool { isEqual(to: date, toGranularity: .year) }
    func isInSameMonth(as date: Date) -> Bool { isEqual(to: date, toGranularity: .month) }
    func isInSameWeek(as date: Date) -> Bool { isEqual(to: date, toGranularity: .weekOfYear) }

    func isInSameDay(as date: Date) -> Bool { Calendar.current.isDate(self, inSameDayAs: date) }

    var isInThisYear:  Bool { isInSameYear(as: Date()) }
    var isInThisMonth: Bool { isInSameMonth(as: Date()) }
    var isInThisWeek:  Bool { isInSameWeek(as: Date()) }

    var isInYesterday: Bool { Calendar.current.isDateInYesterday(self) }
    var isInToday:     Bool { Calendar.current.isDateInToday(self) }
    var isInTomorrow:  Bool { Calendar.current.isDateInTomorrow(self) }

    var isInTheFuture: Bool { self > Date() }
    var isInThePast:   Bool { self < Date() }
    
    func formattedRelativeString() -> String {
        let dateFormatter = DateFormatter()
        
        if self.addingTimeInterval(60) > Date() {
            // less than a minute
            return "Now"
        } else if isInToday || isInYesterday {
            // today and yesterday
            // Today, 3:57 PM
            dateFormatter.doesRelativeDateFormatting = true
            dateFormatter.timeStyle = .short
            dateFormatter.dateStyle = .short
        } else if isInThisWeek {
            // less than a week ago
            // Friday, 4:03 PM
            dateFormatter.dateFormat = "EEEE, h:mm a"
            
        } else if isInThisYear {
            // more than a week ago
            // Fri, 4 Aug, 3:55 AM
            dateFormatter.dateFormat = "E, d MMM, h:mm a"
        } else {
            // more than a year ago
            // 10 Aug, 2016, 3:56 AM
            dateFormatter.dateFormat = "d MMM, yyyy, h:mm a"
        }
            
        return dateFormatter.string(from: self)
    }
}

You can change the date format for each according to your needs. To create your own customized date format refer to this article.

Output

let now = Date().formattedRelativeString()
//  Now

let today = Date(timeInterval: -60*60, since: Date()).formattedRelativeString()
//  Today, 9:06 AM

let yesterday = Date(timeInterval: -24*60*60, since: Date()).formattedRelativeString()
//  Yesterday, 10:06 AM

let weekAgo = Date(timeInterval: -7*24*60*60, since: Date()).formattedRelativeString()
//  Fri, 28 Jul, 10:06 AM

let yearAgo = Date(timeInterval: -366*24*60*60, since: Date()).formattedRelativeString()
//  3 Aug, 2022, 10:06 AM
Sreekuttan
  • 1,579
  • 13
  • 19
-1

Use a NSDateFormatter and set it's doesRelativeDateFormatting property to YES.

rist
  • 578
  • 2
  • 9
  • can you please give me an example for this? – DevCali Jan 20 '14 at 19:06
  • NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.doesRelativeDateFormatting = YES; See https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSDateFormatter_Class/Reference/Reference.html – rist Jan 20 '14 at 19:06