Search code examples
javascripttypescripttimezoneutc

Check if ISO 8601 string is in UTC


I want a TypeScript function that checks if an ISO 8601 datetime string is in UTC. So the output should be:

isUTC('2020-01-01T00:00:00Z')      // true
isUTC('2020-01-01T00:00:00+00')    // true
isUTC('2020-01-01T00:00:00+0000)   // true
isUTC('2020-01-01T00:00:00+00:00') // true
isUTC('2020-01-01T00:00:00+01)     // false
isUTC('2020-01-01T00:00:00+0100)   // false
isUTC('2020-01-01T00:00:00+01:00') // false

If possible I would like to avoid regular expressions and use an existing parser or decomposer instead. Ideally there would be a library that decomposes ISO 8601 strings, so that I can check Iso8601Decomposer(value).timezoneOffset === 0. Does something like this exist in TypeScript/JavaScript?

I found some answers that were checking if value === new Date(Date.parse(value)).toISOString(), but this does not work for lines 2 and 3 above.


Solution

  • You can use the luxon library to parse ISO date strings.

    One can then get the UTC offset in minutes, if this is 0 we're in UTC (or GMT)

    I've wrapped this all up in the required isUTC() function.

    let { DateTime } = luxon;
    
    let inputs = [
        '2020-01-01T00:00:00Z',
        '2020-01-01T00:00:00+00',
        '2020-01-01T00:00:00+0000',
        '2020-01-01T00:00:00+00:00',
        '2020-01-01T00:00:00+01',
        '2020-01-01T00:00:00+0100',
        '2020-01-01T00:00:00+01:00'
    ];
    
    
    function isUTC(input) {
        const dt = DateTime.fromISO(input, { setZone: true })
        return dt.offset === 0;
    }
    
    console.log('Input'.padEnd(30), 'isUTC');
    for(let input of inputs) {
        console.log(input.padEnd(30), isUTC(input));
    }
    .as-console-wrapper { max-height: 100% !important; }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/luxon/2.3.1/luxon.min.js" integrity="sha512-Nw0Abk+Ywwk5FzYTxtB70/xJRiCI0S2ORbXI3VBlFpKJ44LM6cW2WxIIolyKEOxOuMI90GIfXdlZRJepu7cczA==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>

    You can do this with RegEx too:

    let inputs = [
        '2020-01-01T00:00:00Z',
        '2020-01-01T00:00:00+00',
        '2020-01-01T00:00:00+0000',
        '2020-01-01T00:00:00+00:00',
        '2020-01-01T00:00:00+01',
        '2020-01-01T00:00:00+0100',
        '2020-01-01T00:00:00+01:00'
    ];
    
    
    function isUTC(input) {
        return getUTCOffsetMinutes(input) === 0;
    }
    
    function getUTCOffsetMinutes(isoDate) {
        // The pattern will be ±[hh]:[mm], ±[hh][mm], or ±[hh], or 'Z'
        const offsetPattern = /([+-]\d{2}|Z):?(\d{2})?\s*$/;
        if (!offsetPattern.test(isoDate)) {
            throw new Error("Cannot parse UTC offset.")
        }
        const result = offsetPattern.exec(isoDate);
        return (+result[1] || 0) * 60 + (+result[2] || 0);
    }
    
    console.log('Input'.padEnd(30), 'isUTC');
    for(let input of inputs) {
        console.log(input.padEnd(30), isUTC(input));
    }
    .as-console-wrapper { max-height: 100% !important; }