Date variable (Closest to Monday variable)

I know the variable code for inserting today's date is

%ICUDateTime%MM/dd/yyyy%

Is there a code to make it insert the closest Monday to the day that this variable is being used?

Meaning, if it was being used today, a Tuesday, it would enter yesterday's date but it was being used on Friday, it would enter the Monday for the following week.

I believe you have to first figure out the number of days forward or backward needed to get to the closest Monday and then use either %ICUDateTimePlus% or %ICUDateTimeMinus%. I used the DOW() function and some modulo (i.e., division remainder) arithmetic to get the offset from the nearest Monday. The value of DOW() and the offset we need for each day of the week is this:

Day of week   DOW()   Offset
   Sun         1       +1
   Mon         2        0
   Tue         3       -1
   Wed         4       -2
   Thu         5       -3
   Fri         6       +3
   Sat         7       +2

Here's a macro that does the offset calculation and presents the nearest Monday in the format given in the question:

Nearest Monday.kmmacros (3.6 KB)

I admit the first step is a doozy, but it converts what DOW() returns into a number that's either the offset itself (for Monday through Thursday) or a number that's easy to turn into the offset in the if/then step (for Friday through Sunday).

You could undoubtedly avoid the modulo arithmetic by using a handful of if/thens. Maybe someone else will provide a solution that does it that way.

1 Like

Thanks @drdrang, I've included your macro into my larger macro and will test it but so far it seems to work.

I remember doing math similar to this for a project in college—in Fortran 77. I was lucky; my business friends had to use COBOL. Yes, I'm old! :wink:

1 Like

But apparently not old enough to have started with Fortran IV as some of us did. :older_man:

1 Like

Well, I left that part out—I didn't want to sound that old.

When I went to graduate school my advisor had an engineering model running on a PDP-11/Fortran IV programmed with a line printer. Since I was charged with improving the model, I told him that first step would be to port the model the department's brand new, shiny Vax-11/780. There I could use the new modern Fortran 77 and a CRT!

At that same university, another professor didn't know how to use anything but punch cards, so he made us use them for his assignments.

2 Likes

FWIW some JS odds and ends, in case this is needed in KM Execute JavaScript for Automation actions.

(JS uses indexes drawn from [0..6] for [Sun..Sat])

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

    // Indexes: [0..6] = [Sun..Sat]

    // main :: IO ()
    const main = () => {
        const
            now = new Date(),
            monday = 1,
            prev = nearestWeekday(false)(monday)(now),
            next = nearestWeekday(true)(monday)(now);

        const
            elapsed = now - prev,
            remaining = next - now;

        return elapsed < remaining ? (
            prev
        ) : next;
    };

    // --------------------- GENERIC ---------------------

    // nearestWeekday :: Bool -> [0..6] -> Date -> Date
    const nearestWeekday = following =>
        // Looking forward if `following` is `true`,
        // and otherwise looking back:
        // the nearest midnight, in relation to the
        // supplied date, which starts a day of a given
        // weekday index, drawn from [0..6] for [Sun..Sat].
        weekDayIndex => dte => {
            const
                dteCopy = new Date(dte),
                baseIndex = dteCopy.getDay();

            return new Date((
                dteCopy.setDate(
                    dteCopy.getDate() + (
                        following ? (
                            (7 + weekDayIndex) - baseIndex
                        ) : -(baseIndex - weekDayIndex)
                    )
                ),
                dteCopy.setHours(0, 0, 0, 0)
            ));
        };

    return main();
})();