1

次のコードは機能しますが、汚い感じがします。オフセットのあるエポック日付を 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;
}
4

2 に答える 2

3

これを元の要点で試してください

 @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
于 2012-10-04T16:06:38.917 に答える
0

// /Date(-422928000000+0100)/ ドキュメント:

DateTime 値は、"/Date(700000+0500)/" の形式の JSON 文字列として表示されます。ここで、最初の数値 (提供されている例では 700000) は、GMT タイム ゾーン、通常 (非夏時間) のミリ秒数です。 1970 年 1 月 1 日の午前 0 時からの時間。以前の時間を表すために、数値が負になる場合があります。例の「+0500」で構成される部分はオプションであり、時刻がローカルの種類であることを示します。つまり、デシリアライズ時にローカル タイム ゾーンに変換する必要があります。存在しない場合、時刻は Utc として逆シリアル化されます。実際の数値 (この例では "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;
}
于 2012-11-26T23:27:25.360 に答える