2017-02-06 6 views
2

У меня есть два поля, хранящиеся в базе данных, одна из которых содержит дату и время, а другая содержит строку, представляющую продолжительность в формате ISO-8601 (например, «P1MT2H») , Я хочу иметь возможность добавлять продолжительность в столбец datetime в SQL, и кажется, что я должен это сделать, используя DATE_ADD, но я не знаю, есть ли способ конвертировать его в интервал. Я бы предпочел не определять собственную функцию sql, которая, если это возможно, анализирует интервал.MySQL - Преобразование ISO-8601 Продолжительность до интервала для DATE_ADD

+0

Что означает 'P1MT2D'? Я никогда не видел этот формат раньше. Можете ли вы включить ссылку? –

+0

https://en.wikipedia.org/wiki/ISO_8601#Durations –

+0

Я устал, когда я разместил это. Я скорректировал продолжительность – sgcharlie

ответ

0

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

CREATE FUNCTION ADD_ISO_DURATION(StartDate DATETIME, Duration VARCHAR(45), Timezone VARCHAR(45)) 
RETURNS DATETIME 
BEGIN 
    DECLARE TimeStr VARCHAR(45) DEFAULT ''; 
    DECLARE Pos INTEGER; 

    IF StartDate IS NULL OR Duration IS NULL OR LENGTH(Duration) = 0 THEN 
    RETURN StartDate; 
    END IF; 

    IF Timezone IS NOT NULL THEN SET StartDate = CONVERT_TZ(StartDate, 'UTC', Timezone); END IF; 

    IF Duration REGEXP '^P[0-9]+W$' THEN 
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 2, LENGTH(Duration) - 2) WEEK); 
    RETURN IF(Timezone IS NULL, StartDate, CONVERT_TZ(StartDate, Timezone, 'UTC')); 
    END IF; 

    IF Duration NOT REGEXP '^P([0-9]+Y)?([0-9]+M)?([0-9]+D)?(T([0-9]+H)?([0-9]+M)?([0-9]+S)?)?$' THEN 
    RETURN NULL; 
    END IF; 

    SET Pos = LOCATE('T', Duration); 
    IF Pos <> 0 THEN 
    SET TimeStr = SUBSTR(Duration, Pos + 1); 
    SET Duration = SUBSTR(Duration, 2, Pos); 
    ELSE 
    SET Duration = SUBSTR(Duration, 2); 
    END IF ; 

    SET Pos = LOCATE('Y', Duration); 
    IF Pos <> 0 THEN 
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 1, Pos - 1) YEAR); 
    SET Duration = SUBSTR(Duration, Pos + 1); 
    END IF; 

    SET Pos = LOCATE('M', Duration); 
    IF Pos <> 0 THEN 
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 1, Pos - 1) MONTH); 
    SET Duration = SUBSTR(Duration, Pos + 1); 
    END IF; 

    SET Pos = LOCATE('D', Duration); 
    IF Pos <> 0 THEN 
    SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(Duration, 1, Pos - 1) DAY); 
    END IF; 

    IF LENGTH(TimeStr) <> 0 THEN 
    SET Pos = LOCATE('H', TimeStr); 
    IF Pos <> 0 THEN 
     SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(TimeStr, 1, Pos - 1) HOUR); 
     SET TimeStr = SUBSTR(TimeStr, Pos + 1); 
    END IF; 

    SET Pos = LOCATE('M', TimeStr); 
    IF Pos <> 0 THEN 
     SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(TimeStr, 1, Pos - 1) MINUTE); 
     SET TimeStr = SUBSTR(TimeStr, Pos + 1); 
    END IF; 

    SET Pos = LOCATE('S', TimeStr); 
    IF Pos <> 0 THEN 
     SET StartDate = DATE_ADD(StartDate, INTERVAL SUBSTR(TimeStr, 1, Pos - 1) SECOND); 
     SET TimeStr = SUBSTR(TimeStr, Pos + 1); 
    END IF; 
    END IF ; 

    RETURN IF(Timezone IS NULL, StartDate, CONVERT_TZ(StartDate, Timezone, 'UTC')); 
END $$ 
Смежные вопросы