¿Cómo convertir NSDate en formato relativo como “Hoy”, “Ayer”, “hace una semana”, “hace un mes”, “hace un año”?

Quiero convertir nsdate en formato relativo como "Today","Yesterday","a week ago","a month ago","a year ago","date as it is" .

He escrito el siguiente método para ello … pero de alguna manera es solo impresión, ya que es la fecha … ¿pueden decirme cuál debería ser el problema?

// A continuación está mi función que convierte la fecha en una cadena relativa

 +(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]; } 

Tengo una cadena de fecha con el siguiente formato "2013-10-29T09:38:00"

Cuando traté de dar el objeto NSDate, siempre me devuelve una fecha nula.
así que traté de convertir esa fecha en yyyy-MM-dd HH:mm:ssZZZZ luego pasé esta fecha para que funcionase, y luego solo yyyy-MM-dd HH:mm:ssZZZZ fecha completa.

¿Cómo resolver este problema?

// A continuación está el código al que llamo la función anterior

 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; 

Para simplificar, asumo que las fechas en las que está formateando están todas en el pasado (no “mañana” o “la próxima semana”). No es que no se pueda hacer, pero serían más casos con los que lidiar y más cadenas para regresar.


Puede usar components:fromDate:toDate:options: con cualquier combinación de componentes de fecha que esté buscando para obtener la cantidad de años, meses, semanas, días, horas, etc. entre dos fechas. Para luego pasarlos en orden, desde el más significativo (por ejemplo, el año) hasta el menos significativo (por ejemplo, el día), puede formatear una cadena basada solo en el componente más significativo.

Por ejemplo: una fecha que es 1 semana, 2 días y 7 horas atrás se formateará como “1 semana”.

Si desea crear cadenas especiales para un número especial de una unidad, como “mañana” para “1 día atrás”, puede verificar el valor de ese componente después de haber determinado que es el componente más significativo.

El código se vería así:

 - (NSString *)relativeDateStringForDate:(NSDate *)date { NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitWeekOfYear | NSCalendarUnitMonth | NSCalendarUnitYear; // if `date` is before "now" (ie 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"; } } 

Si sus fechas también pueden ser futuras, puede verificar el valor absoluto de los componentes en el mismo orden y luego verificar si es positivo o negativo para devolver las cadenas correspondientes. Solo estoy mostrando el año siguiente:

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

Actualización rápida, gracias a la respuesta objetiva c de David Rönnqvist, funcionará para las fechas pasadas.

 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" (ie 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); } } 

PARA: SWIFT 3

Aquí hay una versión de Swift 3, para fechas pasadas, que maneja todas las unidades y singular o plural en la Cadena devuelta.

Ejemplo de uso:

 let oneWeekAgo = Calendar.current.date(byAdding: .weekOfYear, value: -1, to: Date())! print(relativePast(for: oneWeekAgo)) // output: "1 week ago" 

Lo basé en un riff de Saurabh Yadav. Gracias.

 func relativePast(for date : Date) -> String { let units = Set([.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") } } 

Para evitar el problema de 24 horas mencionado por Budidino a la respuesta de David, lo alteré para que me gustara esto a continuación:

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

Básicamente, crea 2 nuevas fechas sin piezas de tiempo incluidas. Luego la comparación se hace para la diferencia de “días”.

Aquí está mi respuesta (¡en Swift 3 !) Y por qué es mejor.

Responder:

 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 } 

Recuerde reutilizar sus formateadores para evitar cualquier golpe de rendimiento . Sugerencia: las extensiones en DateFormatter y DateComponentsFormatter son buenas ideas.

Por qué es mejor:

  • Utiliza “Yesterday” y “Today” de DateFormatter. ¡Esto ya ha sido traducido por Apple, lo que le ahorra trabajo!
  • Utiliza la cadena traducida de “1 semana” de DateComponentsFormatter. (De nuevo, menos trabajo para usted, cortesía de Apple.) Todo lo que tiene que hacer es traducir la cadena “% @ ago”. 🙂
  • Las otras respuestas calculan incorrectamente el tiempo cuando el día cambia de “hoy” a “ayer”, etc. Las constantes fijas son un gran NO-NO porque las razones . Además, las otras respuestas usan la fecha / hora actual cuando deberían usar el final de la fecha / hora del día actual .
  • Utiliza la actualización automática de Calendario y configuración regional, lo que garantiza que su aplicación esté actualizada de inmediato con el calendario del usuario y las preferencias de idioma en Settings.app

Esta respuesta fue inspirada por DateTools en GitHub.

compruebe NSDate-TimeAgo , también es compatible con varios idiomas.

Tendrá que resolver esta lógica usted mismo. Deberá determinar la cantidad de días entre esas dos fechas.

Aquí hay un enfoque relativamente ingenuo:

 + (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 } 

Es ingenuo por una serie de razones:

  1. No toma en cuenta los días bisiestos
  2. Asume que hay 86400 segundos en un día (¡hay segundos de salto!)

Sin embargo, esto al menos debería ayudarlo a dirigirse en la dirección correcta. Además, evite el uso de los nombres de los métodos get . Usar get en un nombre de método generalmente indica que el que llama debe proporcionar su propio buffer de salida. Considere el método de NSArray , getItems:range: y el método de getCharacters:range: , getCharacters:range:

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

Aquí está el código que creé para mi uso:

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

Esto es solo una copia de una respuesta anterior pero regresa Just now si es menos de cinco segundos.

 func relativePast(for date : Date) -> String { let units = Set([.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: "") } } 

El problema con doesRelativeDateFormatting es que está limitado a Yesterday , Today , Tomorrow . Si buscas algo más completo, mira las respuestas aquí .

Complate Code If Futures Dates

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

He adjuntado la demo aquí, en este enlace. TimestampAgo-Demo

Gracias a n00bprogrammer

Editar: – Hice cambios en Sourcetimezone con [NSTimeZone systemTimeZone] porque debido a la zona horaria estática, el problema ocurre en formato GMT o UTC. (el segundo va en menos) y cambia los métodos en desuso.

Aquí está mi solución en Swift 2 que evita el problema de 24 horas al comparar dos fechas con un tiempo cero.

 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] } } 
 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. eg '2 hours ago'") let timeString = formatter.string(from: components) String(format: formatString, timeString!) 

Para formatear el “fecha de origen” dado como “5:56 pm” para hoy, “ayer” para cualquier momento de ayer, “16 de enero” para cualquier día en el mismo año y “16 de enero de 2014”. Estoy publicando mi propio método.

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