Script to calculate length of time between @start("date") & @done("date")?

Hi,

I’m a novice when it comes to scripting, so I’m wondering if anyone could provide any guidance at writing a script that would calculate the number of days it took to complete a task based on the dates listed in the @start and @done tags within a task?

Not sure how to do that or where to start since a TaskPaper doc has multiple @start and @done tags.

Thanks for the consideration!

You want each task which has both a @start and a @done tag to acquire something like a @days(n) tag, (where n is some number of days) ?


For that kind of thing you could begin by pasting the whole of the following rough draft into Script Editor, and setting the language selector at top left to JavaScript, before hitting the run button.

(Experiment first with dummy data to make sure that it’s doing what you want).

( ⌘Z to reverse the effects of the script )

Expand disclosure triangle to view JS source
(() => {
    "use strict";

    // Add a @days(n) tag in any lines which have both
    // @start(date) and @done(date) tags

    // Draft 0.4

    // ------------ JS FOR AUTOMATION CONTEXT ------------

    // main :: IO ()
    const main = () => {
        const doc = Application("TaskPaper").documents.at(0);

        return doc.exists()
            ? doc.evaluate({
                script: `${TaskPaperContext}`,
                withOptions: { docName: doc.name() }
            })
            : "No document open in TaskPaper.";
    };

    // ---------------- TASKPAPER CONTEXT ----------------

    const TaskPaperContext = (editor, options) => {
        const
            outline = editor.outline,
            day = 24 * 60 * 60 * 1000,
            docName = options.docName;


        // accumulation :: (Int, Item) -> IO Int
        const accumulation = (sofar, item) =>
            ["start", "done"].every(
                tag => item.hasAttribute(`data-${tag}`)
            )
                ? daysElapsed(sofar, item)
                : sofar


        // daysElapsed :: (Int, Item) -> IO Int
        const daysElapsed = (sofar, item) => {
            const
                dates = ["done", "start"].map(
                    k => new Date(item.getAttribute(`data-${k}`))
                ),
                elapsed = Math.round(
                    (dates[0] - dates[1]) / day
                );

            return (
                item.setAttribute("data-days", elapsed),
                sofar + elapsed
            );
        };


        let nDocumentDays = 0;

        return (
            outline.groupUndoAndChanges(() => {
                nDocumentDays = outline.items.reduce(
                    accumulation,
                    nDocumentDays
                )
            }),
            `Sum of task days in "${docName}": ${nDocumentDays}`
        );
    };


    // MAIN ---
    return main();
})();

See: Using Scripts · TaskPaper

2 Likes