Convert informal date-times to yyyy-mm-dd [HH:MM] in TaskPaper 3 Preview

date_time
taskpaper
jxa

#1

TaskPaper 3 queries can use informal date-time expressions,

http://guide.taskpaper.com/formatting_dates.html

but the line tags need to use a simple ISO 8601 date-time format

Here is a macro which converts informal expressions when you type a closing parenthesis after them in TaskPaper 3 Preview

e.g.

@due(tomorrow)      ->    @due(2016-02-13)
@alert(may 24 2pm)  ->    @alert(2016-05-24 14:00)
@due(14 days)       ->    @due(2016-02-26 09:55)

etc.

( Untranslatable expressions between the newly closed parentheses are ignored )

Convert parenthesised informal date to ISO.kmmacros (22.5 KB)

Source of JS action

(function () {
    'use strict'

    // ver 0.11 update for TaskPaper 3 Preview build 170
    //          uses new api:
    //              - DateTime.format()
    //              - outline.groupUndoAndChanges()

    // CONVERTING INFORMAL DATES IN TAGS TO TASKPAPER ISO

    // Replaces any date-translatable text either:
    // 1. in the currently extended selection, or
    // 2. between the first pair of parentheses which
    //    contains or precedes the cursor


    function fnTP3(editor, options) {

        // (editor state) -> maybeReplacement
        // () -> {phraseFound: Boolean, isValid:Boolean, line:Item, 
        //          iso:String, from:Integer, to:Integer} 
        function maybeDateEdit(editor) {
            // current line
            var oSeln = editor.selection || undefined;

            if (oSeln) {
                // Extended selection ?
                var oLine = oSeln.startItem,
                    strText = oLine.bodyString,
                    iStart = oSeln.startOffset,
                    iEnd = oSeln.endOffset,
                    lngSeln = iEnd - iStart,
                    strSeln = lngSeln ? strText.slice(iStart, iEnd) : '';


                // or @key(value) tag starting before selection ?
                if (lngSeln < 1) {
                    var brkFrom = strText.slice(0, iStart)
                        .lastIndexOf('('),
                        brkTo = brkFrom !== -1 ? brkFrom + strText.slice(
                            brkFrom
                        )
                        .indexOf(')') : -1,
                        strParen = (
                            (brkFrom !== -1) && (brkTo !== -1)
                        ) ? strText.slice(brkFrom + 1, brkTo) : '';
                }

                // Extended selection gets priority if both
                var strPhrase = strSeln || strParen,
                    blnText = strPhrase.length > 0,
                    strISO = blnText ? DateTime.format(strPhrase.trim()) :
                    '';

                return {
                    phraseFound: blnText,
                    from: blnText ? (lngSeln ? iStart : brkFrom + 1) : undefined,
                    to: blnText ? (lngSeln ? iEnd : brkTo) : undefined,
                    iso: strISO,
                    isValid: (strISO.indexOf('Invalid') === -1),
                    line: blnText ? oLine : undefined
                };
            } else return {};
        }

        // MAIN
        var dctEdit = maybeDateEdit(editor);

        if (dctEdit.phraseFound) {
            if (dctEdit.isValid) {
                var oLine = dctEdit.line,
                    iFrom = dctEdit.from;

                editor.outline.groupUndoAndChanges(function () {
                    oLine.replaceBodyRange(
                        iFrom,
                        dctEdit.to - iFrom,
                        dctEdit.iso
                    );
                });

                return oLine.bodyString; // updated string
            } else return dctEdit.iso; // or error message
        } else return undefined // or nothing

    }

    var tp = Application("TaskPaper"),
        ds = tp.documents,
        strMaybeEdit = ds.length ? ds[0].evaluate({
            script: fnTP3.toString(),
            withOptions: {}
        }) : '';

    tp.activate();

    return strMaybeEdit;
})();

#2

This is awesome Rob!