function parseDateTimeMaybeOffset()

in lib/odata/odatautils.js [893:971]


function parseDateTimeMaybeOffset(value, withOffset, nullOnError) {

    // We cannot parse this in cases of failure to match or if offset information is specified.
    var parts = parseDateTimeRE.exec(value);
    var offset = (parts) ? getCanonicalTimezone(parts[8]) : null;

    if (!parts || (!withOffset && offset !== "Z")) {
        if (nullOnError) {
            return null;
        }
        throw { message: "Invalid date/time value" };
    }

    // Pre-parse years, account for year '0' being invalid in dateTime.
    var year = parseInt10(parts[1]);
    if (year <= 0) {
        year++;
    }

    // Pre-parse optional milliseconds, fill in default. Fail if value is too precise.
    var ms = parts[7];
    var ns = 0;
    if (!ms) {
        ms = 0;
    } else {
        if (ms.length > 7) {
            if (nullOnError) {
                return null;
            }
            throw { message: "Cannot parse date/time value to given precision." };
        }

        ns = formatNumberWidth(ms.substring(3), 4, true);
        ms = formatNumberWidth(ms.substring(0, 3), 3, true);

        ms = parseInt10(ms);
        ns = parseInt10(ns);
    }

    // Pre-parse other time components and offset them if necessary.
    var hours = parseInt10(parts[4]);
    var minutes = parseInt10(parts[5]);
    var seconds = parseInt10(parts[6]) || 0;
    if (offset !== "Z") {
        // The offset is reversed to get back the UTC date, which is
        // what the API will eventually have.
        var timezone = parseTimezone(offset);
        var direction = -(timezone.d);
        hours += timezone.h * direction;
        minutes += timezone.m * direction;
    }

    // Set the date and time separately with setFullYear, so years 0-99 aren't biased like in Date.UTC.
    var result = new Date();
    result.setUTCFullYear(
        year,                       // Year.
        parseInt10(parts[2]) - 1,   // Month (zero-based for Date.UTC and setFullYear).
        parseInt10(parts[3])        // Date.
        );
    result.setUTCHours(hours, minutes, seconds, ms);

    if (isNaN(result.valueOf())) {
        if (nullOnError) {
            return null;
        }
        throw { message: "Invalid date/time value" };
    }

    if (withOffset) {
        result.__edmType = "Edm.DateTimeOffset";
        result.__offset = offset;
    }

    if (ns) {
        result.__ns = ns;
    }

    return result;
}