Calculate Every or Next Day of the Week - JSON included

For an email marketing series, I needed to calculate every nth day of the week.

For instance, I needed the date every Wednesday for 5 weeks, starting from the next upcoming Wednesday.

It took a while, but this formula can adjust for months with 4 or 5 instances of a day, months of various lengths, leap years, and periods that need to change the year between the calculation and the next Wednesday.

Because this is for marketing and I want to get a chance to nurture someone before the next date, if the registration happens on a Wednesday, it calculates the date of the next Wednesday, not the current one.

It’s a bit hairy and it gave me a stout headache, but here it is.

Ok, let’s break this down.

The entire variables consists of 5 nested if(;:wink: statements.

The first part of the if statement finds the current day of the month as a numeral (so April 4 would be “4”) and asks if that number is bigger then the next formula, which finds the day of month of the first Wednesday in that month.

This is the section of the formula that finds the date of the first Wednesday.


The first formatDate( grabs the YYYY-MM of the current month, and the -1 sets the day to the first day of the month. The outer formatDate grabs that first day of the month and reports back an abbreviated day of the week (Sun, Mon, Tue, etc).

Since I want the next Wednesday, the Switch function swaps the abbreviated day with the number of days I would have to add to that day to get to Wednesday. So, if the formula is trigger on Sun, we would need to add 4 days to get to Tuesday. And since Sunday is the first day of that month, the next Tuesday is the first Tuesday of the month.

Now I have both the current day of the month as a numeral and the first Wednesday of the month as a numeral. If the current date is smaller (before) the first Wednesday, the date is set for that first Wednesday.

If the day of the month is after the first Wednesday, then it moves to the next formula.

That next formula is very similar.

It once again grabs the current day of the month and asks if that number is equal to or less than the second Wednesday of the month.

That second Wednesday is calculated by using the same formula that found the first Wednesday and adding 7 (getting to the second Wednesday of the month).

The date isn’t before the first Wednesday (we ruled that out in the first if(, so if it’s before the second Wednesday then that Wednesday must be the date I want.

The third if( adds 14 to the first Wednesday and the fourth if( adds 21 to the first Wednesday.

If it gets past the 4th if(, which asks if the current date is before the 4th Wednesday of the month, and fails the if(, then we take the date calculation of the 4th Wednesday and add 7 days to it, which will wrap us back around to the first Wednesday of the following month (or year) without needing to calculate the number of days in a month or manually accounting for a year.

Here’s the JSON if anyone like to use this.

I included a few other breakdowns I used while developing this formula as well.

Time and Date Calculation.json (17.4 KB)

2 Likes

Instead of formatDate with ddd and then doing a 7-output switch, why not just use d for day of week number, then calculate the offset to Wed?

According to the Tokens you can use to format a date variable, you can use d.

e.g.: {{ formatDate(now; "d") }}

samliewrequest private consultation

Join the unofficial Make Discord server to chat with other makers!

1 Like

Instead of doing this just to get the days in current month,

you could just do this

2 Likes

You could probably do things with much more maintainable functions,

Output (ran on 7th June Friday)

Screenshot_2024-06-07_230613

Screenshot_2024-06-07_230634

and then you can easily calculate the next days in the current month from there.

samliewrequest private consultation

Join the unofficial Make Discord server to chat with other makers!

2 Likes

Now that’s what I call an optimization of clarity. Great job. I could easily read your function @samliew and understand how you get there.

2 Likes

Yeah, that is easier. Thanks!

Ya know, I tried something similar to begin with, but saw setDay was a day of the week, and hadn’t thought to combine it with setDate to get the first day of the month then scale it up from there.

I guess this whole thread has become a lesson in “easy way” and “hard way” to do something.

:point_up: Honestly this phrase can be applied to all of computer science. And in Make there are so many ways to do the same thing, some that burn operations and some that are super efficient. Sometimes efficiency of operation costs when it comes to clarity, but in this case a more efficient approach has the exactly the opposite effect – it is clearer too!

1 Like

Module Export

You can copy and paste this module export into your scenario. This will paste the modules shown in my screenshots above.

  1. Copy the JSON code below by clicking the copy button when you mouseover the top-right of the code block
    Screenshot_2024-01-17_200117

  2. Enter your scenario editor. Press ESC to close any dialogs. Press CTRLV (paste keyboard shortcut for Windows) to paste directly in the canvas.

  3. Click on each imported module and save it for validation. You may be prompted to remap some variables and connections.

View Module Export Code

JSON

{
    "subflows": [
        {
            "flow": [
                {
                    "id": 2,
                    "module": "util:SetVariables",
                    "version": 1,
                    "parameters": {},
                    "mapper": {
                        "variables": [
                            {
                                "name": "Days in Current Month",
                                "value": "{{floor(formatDate(setDate(addMonths(now; 1); 1) - 86400000; \"D\"))}}"
                            },
                            {
                                "name": "First Monday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 2); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "First Tuesday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 3); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "First Wednesday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 4); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "First Thursday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 5); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "First Friday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 6); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "First Saturday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 0); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "First Sunday Current Month",
                                "value": "{{setSecond(setMinute(setHour(addDays(setDay(setDate(now; 1); 1); if(formatDate(setDay(setDate(now; 1); 2); \"M\") = formatDate(addMonths(now; -1); \"M\"); 7; 0)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Monday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 1) > now; setDay(now; 2); setDay(now; 9)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Tuesday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 2) > now; setDay(now; 3); setDay(now; 10)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Wednesday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 3) > now; setDay(now; 4); setDay(now; 11)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Thursday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 4) > now; setDay(now; 5); setDay(now; 12)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Friday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 5) > now; setDay(now; 6); setDay(now; 13)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Saturday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 6) > now; setDay(now; 0); setDay(now; 7)); 0); 0); 0)}}"
                            },
                            {
                                "name": "Next Sunday",
                                "value": "{{setSecond(setMinute(setHour(if(setDay(now; 0) > now; setDay(now; 1); setDay(now; 8)); 0); 0); 0)}}"
                            }
                        ],
                        "scope": "roundtrip"
                    },
                    "metadata": {
                        "designer": {
                            "x": 300,
                            "y": 0,
                            "name": "Sam's Time & Date Changes"
                        },
                        "restore": {
                            "expect": {
                                "variables": {
                                    "items": [
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null,
                                        null
                                    ]
                                },
                                "scope": {
                                    "label": "One cycle"
                                }
                            }
                        },
                        "expect": [
                            {
                                "name": "variables",
                                "type": "array",
                                "label": "Variables",
                                "spec": [
                                    {
                                        "name": "name",
                                        "label": "Variable name",
                                        "type": "text",
                                        "required": true
                                    },
                                    {
                                        "name": "value",
                                        "label": "Variable value",
                                        "type": "any"
                                    }
                                ]
                            },
                            {
                                "name": "scope",
                                "type": "select",
                                "label": "Variable lifetime",
                                "required": true,
                                "validate": {
                                    "enum": [
                                        "roundtrip",
                                        "execution"
                                    ]
                                }
                            }
                        ],
                        "interface": [
                            {
                                "name": "Days in Current Month",
                                "label": "Days in Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Monday Current Month",
                                "label": "First Monday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Tuesday Current Month",
                                "label": "First Tuesday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Wednesday Current Month",
                                "label": "First Wednesday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Thursday Current Month",
                                "label": "First Thursday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Friday Current Month",
                                "label": "First Friday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Saturday Current Month",
                                "label": "First Saturday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "First Sunday Current Month",
                                "label": "First Sunday Current Month",
                                "type": "any"
                            },
                            {
                                "name": "Next Monday",
                                "label": "Next Monday",
                                "type": "any"
                            },
                            {
                                "name": "Next Tuesday",
                                "label": "Next Tuesday",
                                "type": "any"
                            },
                            {
                                "name": "Next Wednesday",
                                "label": "Next Wednesday",
                                "type": "any"
                            },
                            {
                                "name": "Next Thursday",
                                "label": "Next Thursday",
                                "type": "any"
                            },
                            {
                                "name": "Next Friday",
                                "label": "Next Friday",
                                "type": "any"
                            },
                            {
                                "name": "Next Saturday",
                                "label": "Next Saturday",
                                "type": "any"
                            },
                            {
                                "name": "Next Sunday",
                                "label": "Next Sunday",
                                "type": "any"
                            }
                        ]
                    }
                }
            ]
        }
    ],
    "metadata": {
        "version": 1
    }
}

samliewrequest private consultation

Join the unofficial Make Discord server to chat with other makers!

1 Like