日期原諒我,因爲我是新來的目的C.解析JSON在IPhone
我取回從/日期(XXXXXXXXXXXXX-XXXX)/格式的.NET Web服務的日期。我正在尋找一些關於如何最好的解析NSDate對象的方向。我已經嘗試使用dateWithTimeIntervalSince1970上它,但它回來與在1969年的日期,我知道是在2006年的日期。
尋找一些正確的方式來處理JSON日期。
在此先感謝!
日期原諒我,因爲我是新來的目的C.解析JSON在IPhone
我取回從/日期(XXXXXXXXXXXXX-XXXX)/格式的.NET Web服務的日期。我正在尋找一些關於如何最好的解析NSDate對象的方向。我已經嘗試使用dateWithTimeIntervalSince1970上它,但它回來與在1969年的日期,我知道是在2006年的日期。
尋找一些正確的方式來處理JSON日期。
在此先感謝!
作爲一名.NET程序員學習Objective-C,當我嘗試使用.Net WebService時,我遇到了同樣的問題。
起初我還以爲我將能夠使用NSDateFormatter ... 我發現它的符號here一個很好的參考,但我很快意識到,我需要的數量從毫秒轉換爲秒。
我寫的代碼做... 我還在學習對象 - 但我不認爲它應該一直這個硬...
- (NSDate *) getJSONDate{
NSString* header = @"/Date(";
uint headerLength = [header length];
NSString* timestampString;
NSScanner* scanner = [[NSScanner alloc] initWithString:self];
[scanner setScanLocation:headerLength];
[scanner scanUpToString:@")" intoString:×tampString];
NSCharacterSet* timezoneDelimiter = [NSCharacterSet characterSetWithCharactersInString:@"+-"];
NSRange rangeOfTimezoneSymbol = [timestampString rangeOfCharacterFromSet:timezoneDelimiter];
[scanner dealloc];
if (rangeOfTimezoneSymbol.length!=0) {
scanner = [[NSScanner alloc] initWithString:timestampString];
NSRange rangeOfFirstNumber;
rangeOfFirstNumber.location = 0;
rangeOfFirstNumber.length = rangeOfTimezoneSymbol.location;
NSRange rangeOfSecondNumber;
rangeOfSecondNumber.location = rangeOfTimezoneSymbol.location + 1;
rangeOfSecondNumber.length = [timestampString length] - rangeOfSecondNumber.location;
NSString* firstNumberString = [timestampString substringWithRange:rangeOfFirstNumber];
NSString* secondNumberString = [timestampString substringWithRange:rangeOfSecondNumber];
unsigned long long firstNumber = [firstNumberString longLongValue];
uint secondNumber = [secondNumberString intValue];
NSTimeInterval interval = firstNumber/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
unsigned long long firstNumber = [timestampString longLongValue];
NSTimeInterval interval = firstNumber/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
希望有人能提供更好的Obj-C解決方案。 如果不是我可以收下這筆或者尋找一種方式來改變序列化格式在.NET
編輯:
有關JSON DateTime格式... 如果您對本服務的任何控制它可能會最好將日期轉換爲DataContract對象中的字符串。
Formatting to RFC1123對我來說似乎是個好主意。正如我可以輕鬆地使用NSDateFormatter來撿起它。
報價從Rick Strahl
有沒有JavaScript的日期文字和微軟設計的自定義日期格式,本質上是一種標記的字符串。格式是經過編碼幷包含標準新Date(1970年以來的毫秒)值的字符串。
我在同一條船上,同時使用json-framework,它不支持日期格式,因爲它不是官方的JSON。我的源代碼來自使用JSON.Net構建的API。這是我想出了:
- (NSDate*) getDateFromJSON:(NSString *)dateString
{
// Expect date in this format "/Date(1268123281843)/"
int startPos = [dateString rangeOfString:@"("].location+1;
int endPos = [dateString rangeOfString:@")"].location;
NSRange range = NSMakeRange(startPos,endPos-startPos);
unsigned long long milliseconds = [[dateString substringWithRange:range] longLongValue];
NSLog(@"%llu",milliseconds);
NSTimeInterval interval = milliseconds/1000;
return [NSDate dateWithTimeIntervalSince1970:interval];
}
我沒有在日期格式,你這樣做,我還沒有處理,像上述的答案附加部分。沒有任何錯誤,這一點對我來說都是新的。
我剛剛寫了iOS 4.0+(因爲它使用NSRegularExpression)。它處理帶或不帶時區偏移量的日期。似乎工作得很好,你怎麼看?
+ (NSDate *)mfDateFromDotNetJSONString:(NSString *)string {
static NSRegularExpression *dateRegEx = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
dateRegEx = [[NSRegularExpression alloc] initWithPattern:@"^\\/date\\((-?\\d++)(?:([+-])(\\d{2})(\\d{2}))?\\)\\/$" options:NSRegularExpressionCaseInsensitive error:nil];
});
NSTextCheckingResult *regexResult = [dateRegEx firstMatchInString:string options:0 range:NSMakeRange(0, [string length])];
if (regexResult) {
// milliseconds
NSTimeInterval seconds = [[string substringWithRange:[regexResult rangeAtIndex:1]] doubleValue]/1000.0;
// timezone offset
if ([regexResult rangeAtIndex:2].location != NSNotFound) {
NSString *sign = [string substringWithRange:[regexResult rangeAtIndex:2]];
// hours
seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:3]]] doubleValue] * 60.0 * 60.0;
// minutes
seconds += [[NSString stringWithFormat:@"%@%@", sign, [string substringWithRange:[regexResult rangeAtIndex:4]]] doubleValue] * 60.0;
}
return [NSDate dateWithTimeIntervalSince1970:seconds];
}
return nil;
}
+1此函數支持1970年1月1日之前和之後的日期,這與其他方法的「無符號」毫秒不同。我的解決方案需要TZ的信息,所以我剛剛評論說部分和關閉的比賽。 – J3RM 2012-01-18 17:46:55
+1,這工作正常。什麼是@「^ \\/date \\(( - ?\\ d ++)(?:([+ - ])(\\ d {2})(\\ d {2}))?\ \)\\/$「。我無法理解它正在發生什麼。 – 2013-05-10 05:11:06
@ g-ganesh這是正則表達式。它解析這種格式:「/ Date(xxxxxxxxxxxxx-xxxx)/」。第一部分是unix時間,第二部分是時區。首先,所有那些雙「\」,因爲「\」需要在NSString對象中轉義,然後單個「\」在正則表達式中轉義。所以我們有「^ \/date \(」,它只在字符串的開始處匹配「/ date(」),然後我們有「( - ?\ d ++)」,它捕獲可選的負秒,其中至少有兩個數字(我不記得爲什麼它必須至少有兩個) – jasongregori 2013-05-10 15:33:18
我居然發現NSRegularExpression片斷非常有用的,直到我與使用NSCharecterSet爲stipping關閉毫秒另一種解決方案上來。
+ (NSDate*) dateFromJSONString:(NSString *)dateString
{
NSCharacterSet *charactersToRemove = [[ NSCharacterSet decimalDigitCharacterSet ] invertedSet ];
NSString* milliseconds = [dateString stringByTrimmingCharactersInSet:charactersToRemove];
if (milliseconds != nil && ![milliseconds isEqualToString:@"62135596800000"]) {
NSTimeInterval seconds = [milliseconds doubleValue]/1000;
return [NSDate dateWithTimeIntervalSince1970:seconds];
}
return nil;
}
節省了大量的手動字符串處理,並使代碼更清潔。
這是非常好的解決方案。只是想知道爲什麼沒人贊成這個。謝謝。 – 2012-09-01 14:58:28
這不適用於時代之前的日期,因爲它也會剝離最終的符號字符。 – Niels 2013-03-01 14:44:50
理論值:MS編碼的C#日期時間在JSON作爲毫秒自1970年以來 解決方案:
NSString*
dateAsString = @"/Date(1353720343336+0000)/";
dateAsString = [dateAsString stringByReplacingOccurrencesOfString:@"/Date("
withString:@""];
dateAsString = [dateAsString stringByReplacingOccurrencesOfString:@"+0000)/"
withString:@""];
unsigned long long milliseconds = [dateAsString longLongValue];
NSTimeInterval interval = milliseconds/1000;
NSDate* date = [NSDate dateWithTimeIntervalSince1970:interval];
這是我能想到的最短溶液。
這不是假設時間是UTC嗎? – mkral 2013-01-08 14:59:30
- (的NSString *)convertToUTCTime:(的NSString *)strDate {
NSDate *currentDate = [NSDate date];
myDate = [commonDateFormatter dateFromString: strDate];
NSTimeInterval distanceBetweenDates = [currentDate timeIntervalSinceDate:myDate];
return [self stringFromTimeInterval:distanceBetweenDates];
} - (的NSString *)stringFromTimeInterval:(NSTimeInterval)間隔{ NSInteger的TI =(NSInteger的)間隔; NSIteger分鐘數=(ti/60)%60; NSInteger小時=(ti/3600);
if (hours > 24) {
NSInteger days = hours/24;
if (days > 30) {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"EEE d MMM, h:mm a"];
//[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"IST"]];
NSString *daydate = [dateFormatter stringFromDate:myDate];
return daydate;
}
else{
return [NSString stringWithFormat:@" %2ldd",(long)days];
}
}else{
if (hours == 0 && minutes < 1) {
return [NSString stringWithFormat:@"Today"];
}
else if (hours == 0 && minutes < 60){
return [NSString stringWithFormat:@"%2ldm ",(long)minutes];
}
else{
return [NSString stringWithFormat:@" %2ldh",(long)hours];
}
}
}
感謝您的回答。我基本上採取了與你相同的方法。這感覺像一個黑客,我希望有一個更清潔的解決方案,但哦,它現在工作。 – user213517 2009-11-19 19:09:24
[scanner dealloc];不應該是[掃描儀發佈]; ! :) – 2012-11-12 17:56:04
很好的解決方案,但secondNumber被解析後根本不使用。它應該更正格林威治標準時間日期 – ajonnet 2013-08-01 07:18:46