Reputation: 398
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?
Upvotes: 2
Views: 2630
Reputation: 1964
I have tried all the above solutions but unfortunately, nothing worked for me. Anyway, I ended up with a solution.
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.
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
Upvotes: 0
Reputation: 2328
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)
}
}
Upvotes: 8
Reputation: 152
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;
}
Upvotes: 0
Reputation: 13900
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())
Upvotes: 2
Reputation: 631
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)
}
}
Upvotes: 2
Reputation: 860
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.
Upvotes: 3
Reputation: 578
Use a NSDateFormatter and set it's doesRelativeDateFormatting
property to YES.
Upvotes: -1
Reputation: 1410
NSString *dateString = [NSDateFormatter localizedStringFromDate:[NSDate date]
dateStyle:NSDateFormatterShortStyle
timeStyle:NSDateFormatterFullStyle];
NSLog(@"%@",dateString);
Try this code, modify it as per your requirement.
Upvotes: 0