Time to ISO8601 duration

Benchmark created by Mark Statkus on


Description

Quick test with some time conversion from a Data Object to a ISO 8601 String

Setup

/**
     * Compute Time
     * This is based on seconds not centisecs
     */
    function computeTime(secs, precise) {
        var result,
            years,
            months,
            days,
            hours,
            minutes,
            seconds;
        if (secs === 0) {
            result = "PT0H0M0S";
        } else {
            result = "P";
            if (!precise) {
                years = secs / 31557600;
                secs %= 31557600;
                months = secs / 2629800;
                secs %= 2629800;
            }
            days = secs / 86400;
            secs %= 86400;
            hours = secs / 3600;
            secs %= 3600;
            minutes = secs / 60;
            secs %= 60;
            seconds = secs;
            result += (Math.floor(years) > 0) ? Math.floor(years) + 'Y' : '';
            result += (Math.floor(months) > 0) ? Math.floor(months) + 'M' : '';
            result += (Math.floor(days) > 0) ? Math.floor(days) + 'D' : '';
            result += 'T';
            result += (Math.floor(hours) > 0) ? Math.floor(hours) + 'H' : '';
            result += (Math.floor(minutes) > 0) ? Math.floor(minutes) + 'M' : '';
            result += (Math.floor(seconds) > 0) ? Math.floor(seconds) + 'S' : '';
        }
        return result;
    }
    
    /**
         * Centiseconds To ISO Duration
         * Borrowed from Claude Ostyn, but touched up for JSLint/JavaScript and evil "with" statement
         * @param n {Number} Total Seconds
         * @param bPrecise {Boolean} Only Set true if were dealing with months, years (highly unlikely)
         * @returns {String} SCORM 2004 Time PT0H0M0S Format
         */
        function centisecsToISODuration(n, bPrecise) {
            /* Note: SCORM and IEEE 1484.11.1 require centisec precision
             Parameters:
             n = number of centiseconds
             bPrecise = optional parameter; if true, duration will
             be expressed without using year and/or month fields.
             If bPrecise is not true, and the duration is long,
             months are calculated by approximation based on average number
             of days over 4 years (365*4+1), not counting the extra days
             for leap years. If a reference date was available,
             the calculation could be more precise, but becomes complex,
             since the exact result depends on where the reference date
             falls within the period (e.g. beginning, end or ???)
             1 year ~ (365*4+1)/4*60*60*24*100 = 3155760000 centiseconds
             1 month ~ (365*4+1)/48*60*60*24*100 = 262980000 centiseconds
             1 day = 8640000 centiseconds
             1 hour = 360000 centiseconds
             1 minute = 6000 centiseconds */
            var str = "P",
                nCs = Math.max(n, 0),
                nY = 0,
                nM = 0,
                nD = 0,
                nH,
                nMin;
            // Next set of operations uses whole seconds
            //with (Math) { //argumentatively considered harmful
            nCs = Math.round(nCs);
            if (bPrecise === true) {
                nD = Math.floor(nCs / 8640000);
            } else {
                nY = Math.floor(nCs / 3155760000);
                nCs -= nY * 3155760000;
                nM = Math.floor(nCs / 262980000);
                nCs -= nM * 262980000;
                nD = Math.floor(nCs / 8640000);
            }
            nCs -= nD * 8640000;
            nH = Math.floor(nCs / 360000);
            nCs -= nH * 360000;
            nMin = Math.floor(nCs / 6000);
            nCs -= nMin * 6000;
            //}
            // Now we can construct string
            if (nY > 0) {
                str += nY + "Y";
            }
            if (nM > 0) {
                str += nM + "M";
            }
            if (nD > 0) {
                str += nD + "D";
            }
            if ((nH > 0) || (nMin > 0) || (nCs > 0)) {
                str += "T";
                if (nH > 0) {
                    str += nH + "H";
                }
                if (nMin > 0) {
                    str += nMin + "M";
                }
                if (nCs > 0) {
                    str += (nCs / 100) + "S";
                }
            }
            if (str === "P") {
                str = "PT0H0M0S";
            }
            // technically PT0S should do but SCORM test suite assumes longer form.
            return str;
        }
    
    var startTime = new Date(),
        endTime   = new Date(startTime);
    endTime.setMilliseconds(startTime.getMilliseconds() + (60000 * 5)); // PT5M

Test runner

Ready to run.

Testing in
TestOps/sec
Compute Time
var latency = (endTime.getTime() - startTime.getTime()) / 1000,
    time    = computeTime(latency, false);
ready
Compute Time (precise)
var latency = (endTime.getTime() - startTime.getTime()) / 1000,
    time    = computeTime(latency, true);
ready
Centisecond
var latency = (endTime.getTime() - startTime.getTime()) / 1000,
    time    = centisecsToISODuration(latency * 100, false);
ready
Centisecond (precise)
var latency = (endTime.getTime() - startTime.getTime()) / 1000,
    time    = centisecsToISODuration(latency * 100, true);
ready
Centisecond (multiplication)
var latency = (endTime.getTime() - startTime.getTime()) * 0.001,
    time    = centisecsToISODuration(latency * 100, false);
ready
Centisecond (precise multiplication)
var latency = (endTime.getTime() - startTime.getTime()) * 0.001,
    time    = centisecsToISODuration(latency * 100, true);
ready

Revisions

You can edit these tests or add more tests to this page by appending /edit to the URL.

  • Revision 1: published by Mark Statkus on