Here is my solution to this chapter’s challenge. I think I have used the category correctly, unless I’m missing something about the initialisation. The invalid date handling seems clunky, needs refinement, but trying to be helpful rather than just refuse badly formatted inputs!
main.m
#import <Foundation/Foundation.h>
#import "NSDate+BNRDateConvenience.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
//Pass in some numbers for dates
int day = 12;
int month = 13;
int year = 19;
//Create new date by passing numbers to bnr_dateFromDay:Month:andYear method in new category
NSDate *newDate =[NSDate bnr_dateFromDay:day Month:month andYear:year];
//Set up Date formatter and print out details of new date object
NSDateFormatter *formatter = [[NSDateFormatter alloc]init];
[formatter setDateStyle:NSDateFormatterFullStyle];
[formatter setTimeStyle:NSDateFormatterFullStyle];
NSLog(@"%@", [formatter stringFromDate:newDate]);
}
return 0;
}
NSDate+BNRDateConvenience.h
#import <Foundation/Foundation.h>
@interface NSDate (BNRDateConvenience)
+(NSDate *) bnr_dateFromDay:(int ) d Month:(int) m andYear:(int) y;
@end
NSDate+BNRDateConvenience.m
#import "NSDate+BNRDateConvenience.h"
@implementation NSDate (BNRDateConvenience)
+(NSDate *)bnr_dateFromDay:(int)d Month:(int)m andYear:(int)y
{
//Initialize up a calendar variable
NSCalendar *cal=[NSCalendar currentCalendar];
//Initialize a date component variable
NSDateComponents *comps = [[NSDateComponents alloc]init];
//Initialize a provisional date object
NSDate *provisionalDate = [[NSDate alloc]init];
//Check for invalid dates, guess corrections!
if (y<20) {
y+=2000;
}else if (y<100){
y+=1900;
}
if (m<1) {
m=1;
NSLog(@"Are you sure you entered a correct date?");
}
if (m>12) {
m-=12;
NSLog(@"Are you sure you entered a correct date?");
}
//Add month and year to provisional date
[comps setMonth:m];
[comps setYear:y];
provisionalDate=[ cal dateFromComponents:comps];
//Get range of possible days in month of provisional date
NSRange dayRange =[cal rangeOfUnit:NSDayCalendarUnit inUnit:NSMonthCalendarUnit forDate:provisionalDate];
//Check to see if given day is within range, return nil and message if not, else return updated date
if (d>dayRange.length) {
NSLog(@"Invalid date.");
return nil;
}
if (d<1) {
NSLog(@"Invalid date.");
return nil;
}else{
[comps setDay:d];
provisionalDate=[ cal dateFromComponents:comps];
return provisionalDate;
}
}
@end
Having a slight problem that I think might have to do with timezones. My date keeps coming back two hours early.
I tried reading up in the reference and have so far ended up with this:
[quote=“torjush”]Having a slight problem that I think might have to do with timezones. My date keeps coming back two hours early.
I tried reading up in the reference and have so far ended up with this:
(Have also tried to set the hour, minute and second of my NSDateComponents to zero)
Any tips or hints?[/quote]
hi torjush,
I implemented the method just like you and got the same problem.
Then I used this code to print my date in the main.m file:
NSDate *date = [NSDate bnr_initToMidnightWithYear:2015 month:8 day:21];
NSLog(@"The date is %@", [date descriptionWithCalendarFormat:nil
timeZone:[NSTimeZone systemTimeZone] locale:nil]);
Build and run it and I got
[quote=“wzienrgo”]
hi torjush,
I implemented the method just like you and got the same problem.
Then I used this code to print my date in the main.m file:
NSDate *date = [NSDate bnr_initToMidnightWithYear:2015 month:8 day:21];
NSLog(@"The date is %@", [date descriptionWithCalendarFormat:nil
timeZone:[NSTimeZone systemTimeZone] locale:nil]);
Build and run it and I got
I think this may have fixed the problem.[/quote]
The above provides the correction for the local time zone, but “descriptionWithCalendarFormat” is deprecated as of OS 10.10.
Instead, use “descriptionWithLocale:NSLocaleCalendar” like this:
NSLog(@"The date is %@", [date descriptionWithLocale:NSLocaleCalendar]);
You should get the same output via code that is not deprecated under OS 10.10 (Yosemite).