Archive for July 25th, 2009

Snippet: NaturalDates

Snippet time again: here’s an NSDate category for you to easily provide “Today”, “Yesterday” etc. in Mail.app style, which is a friendly kind of thing to do when you have a date denoted kind of list:

@implementation NSDate (NaturalDates) 

- (BOOL)isSameDay:(NSDate*)anotherDate
{
   NSCalendar* calendar = [NSCalendar currentCalendar];
   NSDateComponents* components1 = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:self];
   NSDateComponents* components2 = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:anotherDate];
   return ([components1 year] == [components2 year] && [components1 month] == [components2 month] && [components1 day] == [components2 day]);
} 

- (BOOL)isToday
{
   return [self isSameDay:[NSDate date]];
} 

- (BOOL)isYesterday
{
   NSCalendar* calendar = [NSCalendar currentCalendar];
   NSDateComponents *comps = [[NSDateComponents alloc] init];
   [comps setDay:-1];
   NSDate *yesterday = [calendar dateByAddingComponents:comps toDate:[NSDate date]  options:0];
   [comps release];
   return [self isSameDay:yesterday];
} 

- (BOOL)isLastWeek
{
   NSCalendar* calendar = [NSCalendar currentCalendar];
   NSDateComponents *comps = [calendar components:NSWeekCalendarUnit|NSDayCalendarUnit fromDate:[NSDate date] toDate:self options:0];
   NSInteger week = [comps week];
   NSInteger days = [comps day];
   return (0==week && days<=0);
} 

- (NSString *)stringFromDateCapitalized:(BOOL)capitalize;
{
   NSString *label = nil;
   NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
   NSString *dateFormatPrefix = nil;
   [dateFormatter setDateStyle:NSDateFormatterNoStyle]; // Will display hour only, we are building the day ourselves
   [dateFormatter setTimeStyle:NSDateFormatterShortStyle];
   if([self isToday])
   {
      if(capitalize) dateFormatPrefix = NSLocalizedString(@"Today at", @"");
      else dateFormatPrefix = NSLocalizedString(@"today at", @"");
   }
   else if([self isYesterday])
   {
      if(capitalize) dateFormatPrefix = NSLocalizedString(@"Yesterday at", @"");
      else dateFormatPrefix = NSLocalizedString(@"yesterday at", @"");
   }
   else if([self isLastWeek])
   {
      NSDateFormatter *weekDayFormatter = [[NSDateFormatter alloc] init];
      // We will set the locale to US to have the weekday in english.
      // The NSLocalizedString(weekDayString, @"") below will make it
      localized.
      NSLocale *locale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US"];
      [weekDayFormatter setLocale:locale];
      [locale release];
      [weekDayFormatter setDateFormat:@"EEEE"];
      NSString *weekDayString = [NSString stringWithFormat:@"%@ at", [weekDayFormatter stringFromDate:self]];
      dateFormatPrefix = NSLocalizedString(weekDayString, @"");
      [weekDayFormatter release];
   }
   else
   {
      [dateFormatter setDateStyle:NSDateFormatterShortStyle]; // Display the date as well
   }
   if(dateFormatPrefix != nil)
   { // We have a day string, add hour only
      label = [NSString stringWithFormat:@"%@ %@", dateFormatPrefix, [dateFormatter stringFromDate:self]];
   }
   else
   { // Use the full date
      label = [dateFormatter stringFromDate:self];
   }
   [dateFormatter release];
   return label;
} 

@end

… yes, we know, it’s just about impossible to actually read the code, we really must get around to finding the time to sort out a theme with a light background and none of this dumb wrapping. One of these days…

h/t: iPhoneSDK!

Continue Reading →
4