Under the Bridge

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!

4
  • http://kosmaczewski.net/ Adrian

    :) for the code, try this plugin http://wordpress.org/extend/plugins/syntaxhighlighter/ I use an earlier version but it’s simply excellent. Cheers! Thanks for the excellent posts.

  • http://www.alexcurylo.com Alex

    Hey, thanks for the tip Adrian. I was actually thinking if I had a white or at least light colored background I could just drag over source from Xcode into that nifty “ecto” editor I’m writing posts with these days and it’s helpful formatting just the way my Xcode theme does wouldn’t disappear into the grey when posted — and besides, the retro feel of the white-on-black thing has pretty much worn off now — but a separate plugin is definitely worth considering too yes.

  • http://foggynoggin.com August Trometer

    Good stuff but it looks like you’ve got a typo. In the isLastWeek method, this:

    [calendarcomponents:NSWeekCalendarUnit|NSDayCalendarUnit…

    Should be this:

    [calendar components:NSWeekCalendarUnit|NSDayCalendarUnit

  • http://www.alexcurylo.com Alex

    Whoops, you are correct of course, space inserted now.