Как проанализировать продолжительность ISO-8601 в Задаче C? - PullRequest
14 голосов
/ 18 июля 2009

Я ищу простой способ разбора строки, которая содержит ISO-8601 продолжительность в Objective C. Результат должен быть чем-то пригодным для использования, например NSTimeInterval.

Пример продолжительности ISO-8601: P1DT13H24M17S, что означает 1 день, 13 часов, 24 минуты и 17 секунд.

Ответы [ 12 ]

0 голосов
/ 07 апреля 2015

Ответы уже есть, но я реализовал еще одну версию, используя NSScanner. Эта версия игнорирует год и месяц, поскольку они не могут быть преобразованы в количество секунд.

static NSTimeInterval timeIntervalFromISO8601Duration(NSString *duration) {
    NSTimeInterval timeInterval = 0;
    NSScanner *scanner = [NSScanner scannerWithString:duration];

    NSCharacterSet *designators = [NSCharacterSet characterSetWithCharactersInString:@"PYMWDTHMS"];
    BOOL isScanningTime = NO;

    while (![scanner isAtEnd]) {
        double scannedNumber = 0;
        BOOL didScanNumber = [scanner scanDouble:&scannedNumber];

        NSString *scanned = nil;
        if ([scanner scanCharactersFromSet:designators intoString:&scanned]) {
            if (didScanNumber) {
                switch ([scanned characterAtIndex:0]) {
                    case 'D':
                        timeInterval += scannedNumber * 60 * 60 * 24;
                        break;
                    case 'H':
                        timeInterval += scannedNumber * 60 * 60;
                        break;
                    case 'M':
                        if (isScanningTime) {
                            timeInterval += scannedNumber * 60;
                        }
                        break;
                    case 'S':
                        timeInterval += scannedNumber;
                        break;
                    default:
                        break;
                }
            }

            if ([scanned containsString:@"T"]) {
                isScanningTime = YES;
            }
        }
    }

    return timeInterval;
}
0 голосов
/ 18 июля 2009

Я посмотрел эту статью Википедии , чтобы узнать, как на самом деле работает ISO-8601. Я не эксперт по какао, но держу пари, если вы сможете разобрать эту строку и извлечь компонент часа, минуты, секунды, день и т. Д., Получить его в NSTimeInterval должно быть легко. Сложная часть разбора этого. Я бы, наверное, сделал это примерно так:

Сначала разбейте строку на две отдельные строки: одну, представляющую дни, и одну, представляющую время. У NSString есть метод экземпляра componentSeparatedByString: NSString, который возвращает NSArray подстрок вашей исходной NSString, разделенных передаваемым параметром. Это будет выглядеть примерно так:

NSString* iso8601 = /*However you're getting your string in*/
NSArray* iso8601Parts = [iso8601 componentsSeparatedByString:@"T"];

Затем найдите первый элемент iso8601Parts для каждого из возможных индикаторов продолжительности дня (Y, M, W и D). Когда вы найдете один, возьмите все предыдущие цифры (и, возможно, десятичную точку), бросьте их в число с плавающей точкой и сохраните их где-нибудь. Помните, что если был только элемент времени, то iso8601Parts [0] будет пустой строкой.

Затем сделайте то же самое, отыскивая части времени во втором элементе iso8601Parts для возможных индикаторов времени (H, M, S). Помните, что если был только дневной компонент (то есть в исходной строке не было символа 'T'), то iso8601Parts будет иметь длину только одну, и попытка получить доступ ко второму элементу вызовет исключение вне границ. .

NSTimeInterval - это всего лишь длительный период, в котором хранится количество секунд, поэтому преобразуйте отдельные фрагменты, которые вы вытащили, в секунды, сложите их вместе, сохраните в NSTimeInterval, и все готово.

Извините, я знаю, что вы попросили "простой" способ сделать это, но, основываясь на моем (по общему признанию) легком поиске и знании API, это самый простой способ сделать это.

...