使用JavaScript转换ISO 8601持续时间

时间:2013-02-18 10:27:31

标签: javascript iso8601

如何使用JavaScript转换持续时间,例如:

PT16H30M

7 个答案:

答案 0 :(得分:14)

理论上,您可以获得ISO8601持续时间,如下所示:

  

P1Y4M3W2DT10H31M3.452S

我编写了以下正则表达式来将其解析为组:

(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?

它不漂亮,而且精通正则表达式的人可能会写出更好的表达。

这些小组归结为以下几点:

  1. 登录
  2. 小时
  3. 分钟
  4. 我编写了以下函数将其转换为一个漂亮的对象:

    var iso8601DurationRegex = /(-)?P(?:([.,\d]+)Y)?(?:([.,\d]+)M)?(?:([.,\d]+)W)?(?:([.,\d]+)D)?T(?:([.,\d]+)H)?(?:([.,\d]+)M)?(?:([.,\d]+)S)?/;
    
    window.parseISO8601Duration = function (iso8601Duration) {
        var matches = iso8601Duration.match(iso8601DurationRegex);
    
        return {
            sign: matches[1] === undefined ? '+' : '-',
            years: matches[2] === undefined ? 0 : matches[2],
            months: matches[3] === undefined ? 0 : matches[3],
            weeks: matches[4] === undefined ? 0 : matches[4],
            days: matches[5] === undefined ? 0 : matches[5],
            hours: matches[6] === undefined ? 0 : matches[6],
            minutes: matches[7] === undefined ? 0 : matches[7],
            seconds: matches[8] === undefined ? 0 : matches[8]
        };
    };
    

    像这样使用:

    window.parseISO8601Duration('P1Y4M3W2DT10H31M3.452S');
    

    希望这可以帮助那些人。


    更新

    如果您使用momentjs,则可以使用ISO8601持续时间解析功能。你需要一个plugin to format它,它似乎不会处理在写这个笔记的那段时间内指定周数的持续时间。

答案 1 :(得分:3)

"PT16H30M".replace(/PT(\d+)H(\d+)M/, "$1:$2");

答案 2 :(得分:3)

我刚刚做了这个,持续时间甚至超过一年 这是fiddle

function convertDuration(t){ 
    //dividing period from time
    var x = t.split('T'),
        duration = '',
        time = {},
        period = {},
        //just shortcuts
        s = 'string',
        v = 'variables',
        l = 'letters',
        // store the information about ISO8601 duration format and the divided strings
        d = {
            period: {
                string: x[0].substring(1,x[0].length),
                len: 4,
                // years, months, weeks, days
                letters: ['Y', 'M', 'W', 'D'],
                variables: {}
            },
            time: {
                string: x[1],
                len: 3,
                // hours, minutes, seconds
                letters: ['H', 'M', 'S'],
                variables: {}
            }
        };
    //in case the duration is a multiple of one day
    if (!d.time.string) {
        d.time.string = '';
    }

    for (var i in d) {
        var len = d[i].len;
        for (var j = 0; j < len; j++) {
            d[i][s] = d[i][s].split(d[i][l][j]);
            if (d[i][s].length>1) {
                d[i][v][d[i][l][j]] = parseInt(d[i][s][0], 10);
                d[i][s] = d[i][s][1];
            } else {
                d[i][v][d[i][l][j]] = 0;
                d[i][s] = d[i][s][0];
            }
        }
    } 
    period = d.period.variables;
    time = d.time.variables;
    time.H +=   24 * period.D + 
                            24 * 7 * period.W +
                            24 * 7 * 4 * period.M + 
                            24 * 7 * 4 * 12 * period.Y;

    if (time.H) {
        duration = time.H + ':';
        if (time.M < 10) {
            time.M = '0' + time.M;
        }
    }

    if (time.S < 10) {
        time.S = '0' + time.S;
    }

    duration += time.M + ':' + time.S;
    alert(duration);
}

答案 3 :(得分:2)

在2.3版中发布的Moment.js具有持续时间支持。

const iso8601Duration = "PT16H30M"

moment.duration(iso8601Duration)
// -> { _data: { days: 0, hours: 16, milliseconds: 0, minutes: 30, months: 0, seconds: 0, years: 0} ... 

moment.duration(iso8601Duration).asSeconds()
// -> 59400

了解更多https://momentjs.com/docs/#/durations/

答案 4 :(得分:0)

专门解决DateTime strings,可以在HTML5 <time/>标记中使用,因为它们仅限于天,分钟和秒(因为只有这些可以转换为精确的秒数,例如月份)和年份可以有不同的持续时间)

function parseDurationString( durationString ){
    var stringPattern = /^PT(?:(\d+)D)?(?:(\d+)H)?(?:(\d+)M)?(?:(\d+(?:\.\d{1,3})?)S)?$/;
    var stringParts = stringPattern.exec( durationString );
    return (
             (
               (
                 ( stringParts[1] === undefined ? 0 : stringParts[1]*1 )  /* Days */
                 * 24 + ( stringParts[2] === undefined ? 0 : stringParts[2]*1 ) /* Hours */
               )
               * 60 + ( stringParts[3] === undefined ? 0 : stringParts[3]*1 ) /* Minutes */
             )
             * 60 + ( stringParts[4] === undefined ? 0 : stringParts[4]*1 ) /* Seconds */
           );
}

测试数据

"PT1D"         returns  86400
"PT3H"         returns  10800
"PT15M"        returns    900
"PT1D12H30M"   returns 131400
"PT1D3M15.23S" returns  86595.23

答案 5 :(得分:0)

ISO8601期间支持的基本解决方案。

由于JavaScript中缺少“持续时间”类型和怪异的日期语义,因此使用日期算法将“句点”应用于“锚定”日期(默认为当前日期和时间)。 默认为添加期间。

指定以前:为true表示过去的日期。

    // Adds ISO8601 period: P<dateparts>(T<timeparts>)?
    // E.g. period 1 year 3 months 2 days:  P1Y3M2D
    // E.g. period 1H:                      PT1H
    // E.g. period 2 days 12 hours:         P2DT12H
    // @param period string: ISO8601 period string
    // @param ago bool [optiona] true: Subtract the period, false: add (Default)
    // @param anchor Date [optional] Anchor date for period, default is current date
    function addIso8601Period(period /*:string */, ago /*: bool? */, anchor /*: Date? */) {
        var re = /^P((?<y>\d+)Y)?((?<m>\d+)M)?((?<d>\d+)D)?(T((?<th>\d+)H)?((?<tm>\d+)M)?((?<ts>\d+(.\d+)?)S)?)?$/;
        var match = re.exec(period);
        var direction = ago || false ? -1 : 1;
        anchor = new Date(anchor || new Date());
        anchor.setFullYear(anchor.getFullYear() + (match.groups['y'] || 0) * direction);
        anchor.setMonth(anchor.getMonth() + (match.groups['m'] || 0) * direction);
        anchor.setDate(anchor.getDate() + (match.groups['d'] || 0) * direction);
        anchor.setHours(anchor.getHours() + (match.groups['th'] || 0) * direction);
        anchor.setMinutes(anchor.getMinutes() + (match.groups['tm'] || 0) * direction);
        anchor.setSeconds(anchor.getSeconds() + (match.groups['ts'] || 0) * direction);
        return anchor;
    }

无保修。这可能会有怪癖-测试您的用例。

答案 6 :(得分:0)

包装了一个小包装以方便此操作:

function $(id){
  return document.getElementById(id);
}

function Hide(){
    Hide1();
}
function Hide1(){
    var foods = $("foodname").value;
    var sel1 = $("foodgroup").options[0].value;
    var aaa = $("cookie").name;
    var aa = $("cookie");
    var a =  $("cookie").alt;
    
    if ((foods==aaa) && (sel1==a)){
        aa.style.visibility = 'hidden';
    }
}

使用import { parse, serialize } from 'tinyduration'; // Basic parsing const durationObj = parse('P1Y2M3DT4H5M6S'); assert(durationObj, { years: 1, months: 2, days: 3, hours: 4, minutes: 5, seconds: 6 }); // Serialization assert(serialize(durationObj), 'P1Y2M3DT4H5M6S'); npm install --save tinyduration

安装

请参阅:https://www.npmjs.com/package/tinyduration