ISO 8601 継続時間表記を正規表現で抜き出す
ISO 8601 日時の期間文字列から W, Y, M, D, h, m, s を抜き出す。
書式は、P[n]Y[n]M[n]DT[n]H[n]M[n]S
または、P[n]W
/^P(?=(?:\d+(?:\.\d+)?W|(?:\d+(?:\.\d+)?[YMD]){1,3}(?:T(?:\d+(?:\.\d+)?[HMS]){1,3})?|T(?:\d+(?:\.\d+)?[HMS]){1,3})$)(?:(.+)W|(?:(.+)Y)?(?:([\d\.]+)M)?(?:(.+)D)?)(?:T(?:(.+)H)?(?:(.+)M)?(?:(.+)S)?)?$/
Date オブジェクトと継続時間表記の文字列の加算
function addDateDuration (date = new this, iso8601_duration_string, scale = 1) { const //週の値は整数に制限[0-53], Y,M,D,h,m,s 共に少数を許容する REG_ISO8601_DURATION = /^P(?=(?:\d+(?:\.\d+)?W|(?:\d+(?:\.\d+)?[YMD]){1,3}(?:T(?:\d+(?:\.\d+)?[HMS]){1,3})?|T(?:\d+(?:\.\d+)?[HMS]){1,3})$)(?:(.+)W|(?:(.+)Y)?(?:([\d\.]+)M)?(?:(.+)D)?)(?:T(?:(.+)H)?(?:(.+)M)?(?:(.+)S)?)?$/, SECONDS = [ 86400, 3600, 60, 1 ], ONE_DAY = 365.2422 / 12, { floor: INT, ceil: CEIL } = Math; let parm = REG_ISO8601_DURATION.exec (iso8601_duration_string); if (parm) { let [, W, Y, M, D, h, m, s] = parm.map (n=> parseFloat (n) || 0), YM = Y * 12 + M,//Y,M の端数はDに加算して切り捨てる (時分秒に影響しない) ms = [D + W * 7 + INT ((YM % 1) * ONE_DAY), h, m, s].reduce ((a, b, i)=> a + b * SECONDS[i], 0) * 1000; date.setMonth (date.getMonth () + INT (YM * scale)); date.setTime (date.getTime () + INT (ms * scale)); return date; } else throw new Error ('Error!!: 解析できない文字列です。/:' + iso8601_duration_string); }