Разбор даты JSON на IPhone
Простите меня, поскольку я новичок в Objective C.
Я возвращаюсь к датам веб-службы .NET в формате /Date (xxxxxxxxxxxxx-xxxx)/. Я ищу какое-то направление, как лучше всего разобрать это в объект NSDate. Я пробовал использовать dateWithTimeIntervalSince1970, но он возвращается с датой в 1969 году на дату, которую я знаю в 2006 году.
Ищете какое-то направление для правильной обработки дат JSON.
Спасибо заранее!
Ответы
Ответ 1
Как изучение .NET-программиста Objective-C У меня была такая же проблема, когда я пытался использовать .Net WebService.
Сначала я подумал, что смогу использовать NSDateFormatter...
Я нашел действительно хорошую ссылку для этого символа здесь, но я быстро понял, что мне нужно преобразовать число от миллисекунд к секундам.
Я написал код, чтобы сделать это...
Я все еще изучаю Obj-C, но я не думаю, что это должно было быть так сложно...
- (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
EDIT:
Об этом формате JSON DateTime...
Если у вас есть какой-либо контроль над сервисом, вероятно, лучше всего преобразовать дату в строку в объекты DataContract.
Форматирование в RFC1123 кажется для меня хорошей идеей прямо сейчас. Как я могу, вероятно, легко поднять его, используя NSDateFormatter.
Цитата из Рик Страл
Нет букв даты JavaScript, и Microsoft разработала собственный формат даты, который по существу является помеченной строкой. Формат - это строка, которая закодирована и содержит стандартное новое значение Date (миллисекунды с 1970 года).
Ответ 2
Я только что написал это для 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;
}
Ответ 3
Я был на одной лодке, используя json-framework, который не поддерживает формат даты, поскольку он не является официальным JSON. Мой источник - это API, построенный с использованием JSON.Net. Вот что я придумал:
- (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];
}
У меня нет добавленной части в формате даты, который вы делаете, поэтому я не рассматривал это как ответ выше. Никакой ошибки не поймать, это все новое для меня в этот момент.
Ответ 4
Я действительно нашел фрагмент с NSRegularExpression довольно полезным, пока я не придумал другое решение, которое использует NSCharecterSet для отмирания миллисекунд.
+ (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;
}
Сохраняет большую часть ручной обработки строк и делает код намного чище.
Ответ 5
Теория: MS кодировала С# DateTime в 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];
Это кратчайшее решение, о котором я могу думать.
Ответ 6
Используйте NSDateFormatter
dateFromString:
после установки формата даты.
Ответ 7
- (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) интервал; NSInteger minutes = (ti/60)% 60; NSInteger hours = (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];
}
}
}