본문 바로가기

iOS개발팁

안전하게 현재 날짜 구하기.

아래의 내용을 맥부기 네이버 카페에도 올렸었습니다. 그 결과 참 소중한 결과를 얻었습니다. 결론은 아래의 글은 제가 실수한 내용입니다. 맥부기 네이버 카페의 '로지아'님께서 날짜를 문자열로 비교할 때에는 description을 사용하는 것은 위험하니 NSDateFormatter를 사용해서 비교할 날짜의 문자열을 출력해야 한다는 것이었습니다. 로지아님의 조언을 바탕으로 아래의 코드를 작성해 보았습니다.
#import <UIKit/UIKit.h>


int main(int argc, char *argv[]) {
   
    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
   
    //테스트할 날짜를 만든다
    NSCalendar *cal = [[[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar] autorelease];
    NSDateComponents *dateComp = [cal components:(NSYearCalendarUnit | NSMonthCalendarUnit) fromDate:[NSDate date]];
    [dateComp setDay:1];
    [dateComp setMonth:9];
    [dateComp setYear:2010];
    [dateComp setHour:0];
    [dateComp setMinute:0];
    [dateComp setSecond:0];
   
    //NSDate description의 위험성!   
    NSLog(@"date01 %@", [[cal dateFromComponents:dateComp] description]);
   
    //NSDateFormatter를 이용해서 날짜의 스트링을 얻어야 정확하다.
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setLocale:[NSLocale currentLocale]];
    [formatter setTimeStyle:NSDateFormatterFullStyle];
    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];
   
   
    NSLog(@"date02 %@", [formatter stringFromDate:[cal dateFromComponents:dateComp]]);
   
   
    int retVal = UIApplicationMain(argc, argv, nil, nil);

    [pool release];
    return retVal;
}
결과는 아래와 같습니다.
iOS 4.0
2010-09-27 12:42:18.708 nsdateTest[2177:207] date01 2010-09-01 00:00:00 +0900
2010-09-27 12:42:18.709 nsdateTest[2177:207] date02 2010-09-01 00:00:00

iOS 4.1
2010-09-27 12:43:32.182 nsdateTest[2236:207] date01 2010-08-31 15:00:00 GMT
2010-09-27 12:43:32.184 nsdateTest[2236:207] date02 2010-09-01 00:00:00

즉, 날짜를 문자열로 비교할 때에는 NSDateFormatter를 이용해서 해당 날짜의 스트링을 얻어와야 버전에 관계 없는 날짜 문자열을 얻어 올 수 있었습니다. 로지아님! 정말 감사합니다.^-^

앞으로는 맥부기에 자주 글을 써야할 것 같습니다. 그래야 제가 가지고 있을지 모르는 오류를 잡을 수 있을테니까요.^-^


iOS가 자주 업데이트 되면서 API의 리턴값이 변경하는 경우가 있습니다. 특히 NSDate의 리턴값이 개발자들을 골탕먹이고 있습니다. 이유는 iOS 4.02까지는 [NSDate date]를 하면 알아서 GMT를 더해서 결과를 반환했지만 iOS 4.1에서는 GMT값을 더하지 않고 반환하기 때문입니다.

이 문제로 4.02까지는 오늘 날짜가 예를 들어 9월 1일이라고 할 때 [NSDate date]를 하면 9월 1일이 잘 출력 되었지만 4.1부터는 8월 31일로 출력됩니다.  NSDate와 같이 자주 사용되고 민감한 API의 반환값을 쉽사리 바꾸는 애플의 업데이트 정책이 조금 황당하기까지 합니다.

문제는 4.1에서 변경한 내용이 언제 다시 바뀔지 모른다고 합니다. 다음 iOS 버전에서는 예전처럼 다시 GMT를 더해서 값을 반환할지도 모른다는 것입니다.

제가 게흘러서 이렇게 중요한 API의 반환값이 변경된다는 얘기를 찾지 못해서 일까요? NSDate처럼 자주 사용되고 민감한 API의 반환값 변경은 좀 신중히 그리고 iOS개발자들이 모두 인지할 수 있도록 계속적인 공지가 필요할 것 같습니다.

그럼 버전별로 달라지는 문제를 어떻게 해결할 수 있을까요? 그냥 항상 GMT를 구해서 현재 시간에 더해 주면 됩니다. 현재 테스트결과 별 문제가 없지만 혹시 또 모르니 iOS의 버전을 검사해서 4.1경우에만 GMT를 더해 주는게 더 좋을 것 같습니다.

NSDate *d = [NSDate date];
if([[[UIDevice currentDevice] systemVersion] isEqualToString:@"4.1"])
{   
        NSTimeZone* currentTimeZone = [NSTimeZone localTimeZone];
        NSInteger currentGMTOffset = [currentTimeZone secondsFromGMT];
        d = [d dateByAddingTimeInterval:currentGMTOffset];
}

'iOS개발팁' 카테고리의 다른 글

NSDate와 NSDateFormatter 사용하기 01  (0) 2010.10.06
Twitter-OAuth-iPhone 라이브러리 소개  (0) 2010.10.05
싱글턴을 활용하자.  (1) 2010.07.30
컬러픽커 만들기  (2) 2010.07.30
아이폰과 아이패드 구분하기  (0) 2010.07.29