2012-09-25 4 views
1

다음 코드는 작동하지만 더러울 것 같습니다. 거기에 오프셋을 사용하여 신기원을 NSDate로 변환하는 더 표준적인 방법이 있습니까?WCF REST 서비스에서 생성 된 JSON에서 NSDate 가져 오기

- (NSDate *) dateFromJSONString: (NSString *) JSONString{ 
    //expects JSON from .NET WCF Service in epoch ticks, ex: 
    //"timeScheduled":"\/Date(1348600140000+0100)\/" 
    NSString *date = [[JSONString stringByReplacingOccurrencesOfString:@"/Date("   withString:@""] stringByReplacingOccurrencesOfString:@")/" withString:@""]; 
    NSString *offsetString = [date substringFromIndex:(date.length - 5)]; 

    //convert to seconds 
    NSTimeInterval dateInterval = [date doubleValue] /1000; 

    //gets offset value in seconds - +0100 -> 100 -> 1 -> 3600 
    double offsetValue = ([offsetString doubleValue]/100) * 60 * 60; 
    if ([[offsetString substringToIndex:1] isEqualToString:@"+"]) { 
     dateInterval = dateInterval + offsetValue; 
    } 
    else{ 
     dateInterval = dateInterval - offsetValue; 
    } 

    NSDate *retVal = [[NSDate alloc]initWithTimeIntervalSince1970:dateInterval]; 

    return retVal; 
} 

답변

3

the original gist

@implementation NSDate (DotNetDates) 

+(NSDate*) dateFromDotNet:(NSString*)stringDate{ 

NSDate *returnValue; 

if ([stringDate isMemberOfClass:[NSNull class]]) { 
    returnValue=nil; 
} 
else { 
    NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT]; 

    returnValue= [[NSDate dateWithTimeIntervalSince1970: 
        [[stringDate substringWithRange:NSMakeRange(6, 10)] intValue]] 
        dateByAddingTimeInterval:offset]; 
} 

    return returnValue; 

} 
-(NSString*) dateToDotNet{ 
double timeSince1970=[self timeIntervalSince1970]; 
NSInteger offset = [[NSTimeZone defaultTimeZone] secondsFromGMT]; 
offset=offset/3600; 
double nowMillis = 1000.0 * (timeSince1970); 
NSString *dotNetDate=[NSString stringWithFormat:@"/Date(%.0f%+03d00)/",nowMillis,offset] ; 
return dotNetDate; 
} 


@end 
+2

이 링크는 질문에 대한 답변 일지 모르지만 여기에 답변의 핵심 부분을 포함하고 참조 할 수있는 링크를 제공하는 것이 좋습니다. 링크 된 페이지가 변경되면 링크 전용 답변이 유효하지 않게 될 수 있습니다. – fancyPants

+0

충분히 좋습니다. 나는 좀 간결했다. :) –

+0

답변과 코드는 iOS8에서 완벽하게 작동했습니다. – AshesToAshes

0

///일 (+ 0100 -422928000000)를 시도/ 문서는 :

시간 값은 ("/ 일 형태 JSON 문자열로 나타나는 700000 + 0500)/"입니다. 첫 번째 숫자 (제공된 예제에서는 700000)는 1970 년 1 월 1 일 자정 이후 정규 (비 일광 절약 시간) 시간 인 GMT 시간대의 밀리 초입니다. 숫자는 음수 일 수 있습니다 이전의 시간을 나타냅니다. 이 예제에서 "+0500"으로 구성된 부분은 선택적이며 시간이 지역 종류 (즉, 비 직렬화시 로컬 표준 시간대로 변환되어야 함)임을 나타냅니다. 부재중 인 경우 시간은 Utc로 deserialize됩니다. 실제 숫자 (이 예에서는 "0500")와 부호 (+ 또는 -)는 무시됩니다.

NSTimeInterval은 항상 초 단위로 지정됩니다. 그것은 10,000 년의 범위에 걸쳐 밀리 세컨드 이하의 정밀도를 산출합니다.

+ (NSDate*) dateFromDotNet:(NSString *)stringDate{ 
    if(stringDate==(id)[NSNull null]) 
     return nil; 
    NSInteger ix0= [stringDate rangeOfString:@"("].location; 
    NSInteger ix1= [stringDate rangeOfString:@")"].location; 
    if(ix0==NSNotFound || ix1==NSNotFound) 
     @throw [NSException exceptionWithName:@"ExceptionName" reason:@"Invalid JSON data" userInfo:@{@"json":stringDate}]; 
    NSRange range= NSMakeRange(ix0+1, ix1-ix0); 
    NSString *dateString= [stringDate substringWithRange:range]; 
    // dateString: -422928000000+0100  
    NSCharacterSet *signs= [NSCharacterSet characterSetWithCharactersInString:@"+-"]; 
    range= [dateString rangeOfCharacterFromSet:signs option:NSBackwardSearch]; 
    // WCF will send 13 digit-long value for the time interval since 1970 (millisecond precision) 
    // whereas iOS works with 10 digit-long values (second precision), hence the divide by 1000 
    NSTimeInterval unixTime = [dateString doubleValue]/1000; 

    if(range.location!=NSNotFound){ 
     NSString *sign = [dateString substringWithRange:range]; 
     NSString *off = [dateString substringFromIndex:range.location+1]; 
     // gets offset value in seconds -+0100 -> 100 -> 1 -> 3600 
     double offset = ([off doubleValue]/100) * 60 * 60; 
     if ([sign isEqualToString:@"+"]) 
      unixTime+= offset; 
     else 
      unixTime-= offset; 
    } 
    NSDate *date= [NSDate dateWithTimeIntervalSince1970:unixTime]; 
    return date; 
} 
+1

이에 대한 설명을 추가하는 것을 고려해야합니다. – Tyrsius