Reading an OO date cell to a simplified ISO 8601 format string


#1

Background: https://xkcd.com/1179/

(As used in TaskPaper etc text formats)

Snippets in AppleScript, JavaScript for Automation (JXA) , omniJS:

(the latter two in (Sierra-onwards) ES6 Javascript - for pre-Sierra (ES5) versions, paste into the Babel JS REPL at https://babeljs.io/repl)

Assuming a selected row like:


[details=AppleScript]```AppleScript
on run
tell application “OmniOutliner”
tell first selected row of front document

        my iso8601Local(value of cell named "Dates")
        
    end tell
end tell

--> e.g.  "2017-08-16 16:15"

end run

– GENERIC FUNCTIONS ---------------------------------------------------------

– curry :: (Script|Handler) -> Script
on curry(f)
script
on |λ|(a)
script
on |λ|(b)
|λ|(a, b) of mReturn(f)
end |λ|
end script
end |λ|
end script
end curry

– intercalate :: Text -> [Text] -> Text
on intercalate(strText, lstText)
set {dlm, my text item delimiters} to {my text item delimiters, strText}
set strJoined to lstText as text
set my text item delimiters to dlm
return strJoined
end intercalate

– iso8601Local :: Date -> String
on iso8601Local(dte)
tell (dte) to set {y, m, d, t} to {its year, its month as integer, its day, its time}
intercalate("-", {y, zeroPad(2, m), zeroPad(2, d)}) & " " & ¬
intercalate(":", map(|λ|(2) of curry(my zeroPad), ¬
{t div 3600, (t mod 3600) div 60}))
end iso8601Local

– map :: (a -> b) -> [a] -> [b]
on map(f, xs)
tell mReturn(f)
set lng to length of xs
set lst to {}
repeat with i from 1 to lng
set end of lst to |λ|(item i of xs, i, xs)
end repeat
return lst
end tell
end map

– Lift 2nd class handler function into 1st class script wrapper
– mReturn :: Handler -> Script
on mReturn(f)
if class of f is script then
f
else
script
property |λ| : f
end script
end if
end mReturn

– replicate :: Int -> String -> String
on replicate(n, s)
set out to “”
if n < 1 then return out
set dbl to s

repeat while (n > 1)
    if (n mod 2) > 0 then set out to out & dbl
    set n to (n div 2)
    set dbl to (dbl & dbl)
end repeat
return out & dbl

end replicate

– zeroPad :: Int -> String -> String
on zeroPad(n, e)
set s to e as string
set d to n - (length of s)
if d > 0 then
intercalate("", replicate(d, “0”) & s)
else
s
end if
end zeroPad


[details=JavaScript for Automation (JXA)]```JavaScript
  (() => {
    'use strict';

    // iso8601Local :: Date -> String
        const iso8601Local = dte => {
            const xs = ['FullYear', 'Month', 'Date',
                    'Hours', 'Minutes' //, 'Seconds', 'Milliseconds'
                ]
                .map((k, i) => {
                    const s = (dte['get' + k]() + (i === 1 ? 1 : 0))
                        .toString();
                    return (s.length === 1 ? '0' : '') + s;
                });
            return xs.slice(0, 3)
                .join('-') + ((xs[3] !== '00' || xs[4] !== '00') ? (
                    ' ' + xs.slice(3)
                    .join(':')
                ) : '');
        };

        return iso8601Local(
            Application('OmniOutliner')
            .documents[0].selectedRows[0].cells.byName("Dates")
            .value()
        );
    })();
```[/details]


[details=omniJS]```JavaScript
(() => {
    'use strict';

    // isoLocal :: Date -> String
        const isoLocal = dte => {
            const xs = ['FullYear', 'Month', 'Date',
                    'Hours', 'Minutes' //, 'Seconds', 'Milliseconds'
                ]
                .map((k, i) => {
                    const s = (dte['get' + k]() + (i === 1 ? 1 : 0))
                        .toString();
                    return (s.length === 1 ? '0' : '') + s;
                });
            return xs.slice(0, 3)
                .join('-') + ((xs[3] !== '00' || xs[4] !== '00') ? (
                    ' ' + xs.slice(3)
                    .join(':')
                ) : '');
        };

        return isoLocal(
            document.editors[0]     // -> Editor
            .selectedNodes[0]       // -> TreeNode
            .object                 // -> Item (outline row)
            .valueForColumn(        // -> Date
                document.outline        // -> Outline
                .columns                // -> [Column] (array of columns)
                .byTitle('Dates')       // -> Column
            )
        );
    })();

```[/details]