2017-02-06 6 views
2

データベースには2つのフィールドがあり、そのうちの1つは日時を含み、もう1つはISO-8601フォーマットの期間を表す文字列を含みます(例: "P1MT2H")。 。 SQLのdatetime列に継続時間を追加できるようにしたいのですが、DATE_ADDを使用してこれを実行できるはずですが、間隔に変換するには良い方法があるかどうかわかりません。私は可能な場合は、間隔を解析する自分のSQL関数を定義する必要はありませんが好きです。MySQL - DATE_ADDのISO-8601期間をインターバルに変換

+0

「P1MT2D」とは何ですか?私はこれまでこのフォーマットを見たことがない。あなたはリンクを含めることができますか? –

+0

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

+0

これを投稿したとき、私はかなり疲れました。私は期間を修正しました – sgcharlie

答えて

0

私はまだこの質問に対する素敵な答えを聞いていますが、当面はこれを行うための機能を作成しました。特定のタイムゾーンで計算を実行するための3番目のオプションのパラメータを追加しました。それは普遍的な解決策ではありませんが、私はそれが他の人を正しい軌道に乗せることを願っています。

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 $$ 
関連する問題