SideLobe SideLobe - 3 months ago 8
Objective-C Question

Objective-C: find date given day of the year and year

I'm writing a GUI for a legacy data object where a date is saved in the integer properties

day of the year
and
year
(real "genius" design...)

How can I convert this data into day and month given the year?

I'm currently trying:

int theYear = 2016;
int theDayOfTheYear = 222;
NSCalendar* gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *components = [[NSDateComponents alloc] init];
[components setYear:theYear];
[components setDay:theDayOfTheYear];
NSDate* theDate = [gregorian dateFromComponents:components];


This seems a bit too hacky to me. It could be just coincidence that it works with days >31 - haven't found any mention of this in the NSDateComponents class reference.

When I debug,
po theDate
gives me
2016-08-08 22:00:00 +0000

--> close, but it should be
2016-08-09
(!)




To perform the reverse operation, i.e. to convert a normal DD-MM-YYYY date into
day of the year
, I'm using this code:

NSDate *fullDate = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSUInteger dayOfYear = [gregorian ordinalityOfUnit:NSDayCalendarUnit
inUnit:NSYearCalendarUnit
forDate:fullDate];


But I can't seem to find the proper methods to do the opposite...

Answer

Sometimes a test is all takes :)

Don't forget that NSDate are GMT, so you might want to add [[NSTimeZone localTimeZone] secondsFromGMT] seconds to it.

It seems that you have it working :)

- (void) testDate
{
    int startYear = 2016;
    int startMonth = 1;
    int startDay = 1;

    // Create the startDate
    NSDateComponents * startDateComp = [NSDateComponents new];
    startDateComp.day = startDay;
    startDateComp.month = startMonth;
    startDateComp.year = startYear;
    NSDate * startDate = [[NSCalendar currentCalendar] dateFromComponents:startDateComp];


    for(int i=0 ; i < 365; i++)
    {
        // add i day to startDate
        NSDate * testDate = [startDate dateByAddingTimeInterval:i * 24 * 60 * 60];

        NSUInteger dayOfYear = [[NSCalendar currentCalendar] ordinalityOfUnit:NSDayCalendarUnit
                                                                       inUnit:NSYearCalendarUnit
                                                                      forDate:testDate];

        XCTAssert(dayOfYear == (i + 1), @"the day of the year should be i + 1");

        // Create a date using day of year
        NSDateComponents *components = [[NSDateComponents alloc] init];
        [components setYear:startYear];
        [components setDay:dayOfYear];
        NSDate* resultDate = [[NSCalendar currentCalendar] dateFromComponents:components];

        // testing result date against test date

        NSInteger test, result;

        test = [[NSCalendar currentCalendar] component:NSCalendarUnitDay fromDate:testDate];
        result = [[NSCalendar currentCalendar] component:NSCalendarUnitDay fromDate:resultDate];
        XCTAssert(test == result);

        test = [[NSCalendar currentCalendar] component:NSCalendarUnitMonth fromDate:testDate];
        result = [[NSCalendar currentCalendar] component:NSCalendarUnitMonth fromDate:resultDate];
        XCTAssert(test == result);

        test = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:testDate];
        result = [[NSCalendar currentCalendar] component:NSCalendarUnitYear fromDate:resultDate];
        XCTAssert(test == result);

    }