1

NSDate/NSDateFormatter et al seem to take too many lines of code for common tasks.

Is there something better out there for iOS development like DateJS for JavaScript?

Here are some examples of common NSDate usage where the canonical solution could be at least twice as small:

  1. Create a NSDate from integers. Solution: SO Answer 1
  2. Get year/month/day from NSDate. Solution: SO Answer 2
  3. There are more of these common scenarios on SO.
Community
  • 1
  • 1
whitneyland
  • 10,632
  • 9
  • 60
  • 68
  • Can you give us any more specific complaints? Otherwise it's difficult to offer anything other than platitudes. – Tommy Aug 04 '11 at 17:24
  • How is that too many lines of code ? What are you trying to do ? – Legolas Aug 04 '11 at 17:39
  • Added two examples with canonical solutions. "Too many lines of code" has been clarified to mean it could easily be half as many characters or smaller. – whitneyland Aug 06 '11 at 14:36

3 Answers3

7

I don't think there's a better way to natively handle dates. What you could do however is create a few categories on NSDate to make it easier to deal with dates, this is especially useful if you find yourself repeating the same lines of code often.

Edit: here are a few examples:

Wolfgang Schreurs
  • 11,779
  • 7
  • 51
  • 92
  • I agree, categories are probably the best way to do these things. Unfortunately Objective-C is not too familiar with the DRY (Don't Repeat Yourself) paradigm… – Fabian Schuiki Aug 04 '11 at 17:47
  • These are useful, I gave you +1. However I don't mark it as a solution because "common" NSDate scenarios are not covered (see example 2). I justify this case as common because it has more than 10 votes on SO. – whitneyland Aug 06 '11 at 14:34
  • I believe even for those purposes a category will be sufficient most of the time. I will post some code to show how to deal with the 2nd example. – Wolfgang Schreurs Aug 06 '11 at 15:26
1

NSDate is highly efficient and highly productive, especially when combined with NSDateFormatter and NSCalendar, although you could argue the latter classes are quite bloated and 'slow', they are incredibly deep.

What specific complaints do you have?

Benjamin Mayo
  • 6,649
  • 2
  • 26
  • 25
  • First, you are right to ask for specific complaints, I've added a link to try and illustrate.
    Second, I don't see how NSDate could be considered highly productive relative to date classes in other languages. Have you compared productivity to Java/C#/Javascript? Not talking raw performance, just productivity as you say.
    – whitneyland Aug 05 '11 at 15:25
  • Compared to JavaScript, NSDate is much better. Haven't got experience in Java or C# so can't comment. But NSDate (and related API) are extremely useful and productive. Maybe a bit cryptic to understand, but powerful. – Benjamin Mayo Aug 05 '11 at 19:47
  • I refer to JavaScript date handling using DateJS, which actually makes dates a joy to use. Yes it's a add-on/helper, but that is my whole point, why not have such a helper in ObjC so that everyone doesn't have to create their own categories? Guess the solutions out there need more momentum/adoption to become defacto used. – whitneyland Aug 06 '11 at 14:22
  • 2
    I don't see the big issue with NSDate, and related API. It does what you need, extensible and complete enough to extend if necessary. This isn't PHP where you have super-big classes; Obj-C is meant to be compact and concise. If your looking for a "super category" look at the examples from Wolfgang Schruers. – Benjamin Mayo Aug 06 '11 at 18:51
1

With regards to extracting the year / month / day for a NSDate using a category, an example:

NSDate+ComponentsExtractor.h:

#import <Foundation/Foundation.h>

typedef struct 
{
   NSInteger year;
   NSInteger month;
   NSInteger day;
} dateComponents;

@interface NSDate (ComponentsExtractor)
+ (dateComponents)componentsFromDate:(NSDate *)theDate;
@end

NSDate+ComponentsExtractor.m:

#import "NSDate+ComponentsExtractor.h"

@implementation NSDate (ComponentsExtractor)

+ (dateComponents)componentsFromDate:(NSDate *)theDate
{
   NSCalendar *gregorian = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
   unsigned unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit |  NSDayCalendarUnit;
   NSDateComponents *components = [gregorian components:unitFlags fromDate:theDate];

   dateComponents theComponents;
   theComponents.year = [components year];   
   theComponents.month = [components month];
   theComponents.day = [components day];

   return theComponents;
}

@end

Making use of the category:

NSDate *theDate = [NSDate date]; // use the current date ...
dateComponents components = [NSDate componentsFromDate:theDate];
NSLog(@"%i - %i - %i", components.year, components.month, components.day);

I believe pointer indirection could be used as well to achieve similar results, but without needing a struct - it depends whatever one regards as the 'cleanest' solution.

Wolfgang Schreurs
  • 11,779
  • 7
  • 51
  • 92