Date Calculator [Reusable Action]

Use Case

  • Calculating a Date in the future or past that is NOT based on Current Date (although this macro/action will work for current date as well).
  • Basing it on any other date requires use of the ICUDateTimeFOR token with the TIME function which is in GMT.
    • This causes some compromises in time, and complications in Actions to use.
  • The below macro presents one simple Shell Script to made date calculations easy, while providing much flexibility
  • Since ALL of the KM Variables are outside of the actual script, and are entered as Parameters to the Action, it makes changing them easy and reduces errors.
  • It can easily be refactored as a reusable Action.

Reusable Execute Shell Script

# Enter KM Variables (or text) for these Bash Variables
# BaseDate AdjustBy [ AdjustUnits DateFormatIN DateFormatOUT ]
# Variables in brakets [ ] are optional; Must enter prior Variables to not enter subsequent variables.

# Default for Both input and output date format is YYYY-MM-DD

read myBaseDate myAdjust myAdjustUnits myDateFormatIn myDateFormatOut

# --- DEFAULT VALUES If NOT Passed Via stdin ---
myAdjustUnits=${myAdjustUnits:-d}
myDateFormatIn=${myDateFormatIn:-%Y-%m-%d}
myDateFormatOut=+${myDateFormatOut:-%Y-%m-%d}


#              Adjustment              Input Format                 Output Format
date -j -v$myAdjust$myAdjustUnits -f $myDateFormatIn "$myBaseDate" $myDateFormatOut

Example Output

image

image


MACRO:   Date Calculator [Reusable Action]

~~~ VER: 2.0    2018-07-23 ~~~

DOWNLOAD:

Date Calculator [Reusable Action].kmmacros (12 KB)
Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.

As always, please feel free to post any questions, issues, and/or suggestions you may have about this macro.


ReleaseNotes

Author.@JMichaelTX

PURPOSE:

  • Provide a Reusable, Configurable, Action to Calculate Dates
    • While KM provides extensive handling of dates using the ICU tokens & functions, it is very laborous to write a macro which calculates a new date from a date other than the current date.
    • The Action in this macro presents an alternative to using KM ICU tokens.
    • It provides one KM Action, a Shell Script with a Bash date command, to accomplishes this with only 5 lines, and yet is very configurable.
    • It only requires two inputs, which the macro author can enter as KM Variable Tokens in the Execute Shell Script Action Input area, which are Parameters for the script Standard In (stdin):
      • Base Date
      • Adjust by amount (in days, +/-)
    • By Default, the script uses this data, which can be easily overridden:
      • Adjust By Units: Days
      • Date Input Format: ISO 8601 YYYY-MM-DD
      • Date Output Format: ISO 8601 YYYY-MM-DD
      • Override these by adding Parameters to the Script Input area.
      • If you don't like the defaults, you can easily change the defaults in the script.

REQUIRES:

  1. KM 7+
  2. macOS 10.10+ (Yosemite)
    • However, it has been tested ONLY in KM 8.2.2 with macOS 10.12.6 :wink:

How To Use

As a Demo

  1. Just Trigger this macro.
    • Enter the Base Date and Offset
    • Observe Results

As a Reusable Action

  • Save the Execute Shell Script Action somewhere for easy reuse
    (choose one of these:)
    1. I recommend the KMFAM Macro System by @DanThomas
    2. Setup as a Sub-Macro, which can be called using an Execute Macro Action
    • Paste the Script Parameters as Parameters to the Execute Macro Action
    1. Store in a "template" macro where you can copy/paste into new Macros

MACRO SETUP

  • Carefully review the Release Notes and the Macro Actions
    • Make sure you understand what the Macro will do.
    • You are responsible for running the Macro, not me. ??
      .
  1. Assign a Trigger to this maro..
  2. Move this macro to a Macro Group that is only Active when you need this Macro.
  3. ENABLE this Macro.
    .
  • REVIEW/CHANGE THE FOLLOWING MACRO ACTIONS:
    (all shown in the magenta color)
    • Prompt for User Input
      • You can change the defaults for BaseDate and AdjustBy (which MUST include the sign), but do NOT change the Units.

4 Likes

Thanks! That's super helpful and exactly what I was looking for.
However, I would like to make a small adjustment and haven't figured out how.

I would like to show for the OUTPUT the date like "Fr, 2020-04-17". Can that be easy done? I tried a bit, but it's not working. I am anything but an expert to be fair.

Thanks!

It is easy to do once you know how, but a bit tricky in the setup. In order to include a space in the format, the format string must be in quotes.

Use this script for the shell script:

#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Title: Date Calculation
# Ver:   1.1
# Date: 2020-04-17
# Author: JMichaelTX
#~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

# Enter KM Variables (or text) for these Bash Variables
# BaseDate AdjustBy [ AdjustUnits DateFormatIN DateFormatOUT ]
# Variables in brackets [ ] are optional; Must enter prior Variables to not enter subsequent variables.

# Default for Both input and output date format is YYYY-MM-DD

read myBaseDate myAdjust myAdjustUnits myDateFormatIn myDateFormatOut

# --- DEFAULT VALUES If NOT Passed Via stdin ---
myAdjustUnits=${myAdjustUnits:-d}
myDateFormatIn=${myDateFormatIn:-%Y-%m-%d}
# myDateFormatOut=+${myDateFormatOut:-%Y-%m-%d}
myDateFormatOut=+${myDateFormatOut:-"%a, %Y-%m-%d"}


#              Adjustment              Input Format                  Output Format
date -j -v$myAdjust$myAdjustUnits -f $myDateFormatIn "$myBaseDate" "$myDateFormatOut"

The key change is this line:

myDateFormatOut=+${myDateFormatOut:-"%a, %Y-%m-%d"}

For the complete list of formatting codes, see
How To Format Date For Display or Use In a Shell Script

Thanks, that's great news. Thanks a lot!

This macro is fantastic - it goes a long way to meeting a need I've had. But I can't figure this out --

What's the best way to get new dates around the target date?

For example, I'm trying to output a text string that looks something like this:

| [[week # of target date]] | [[day before target date]] | [[target date]] | [[day after target date]] |

This serves as a breadcrumb line at the bottom of text files, with wiki-links to the next and previous days

The formatting isn't an issue, and I can parse out the day, month, year, etc. I just can't figure out how to create a new date based on the %Local__AdjustBy% variable, or the %Local__NewDate% result.

I tried to adjust the value of %Local__AdjustBy% later in the macro by adding one and subtracting one, but it won't work. The macro always fails; I set the calculation of a new variable to Local__AdjustBy + 1, for example, and nothing happens.


Maybe I need to indicate use the value that was input by the user at the prompt?

Maybe it would be better to add and subtract in the script instead.

The end result I think I need is something like:

  • Calculate %DayBefore% from %Local__NewDate% minus 1d
  • Calculate %DayAfter% from %Local__NewDate% plus 1d

That way there is only one target date, and multiple other dates can be created off of that. I've spent hours and can't figure it out.

Again, just to clarify -- what's the best way to get some dates around a static target date?

I don't know if it is the best way, but here's a pretty good way:

Below is just an example written in response to your request. You will need to use as an example and/or change to meet your workflow automation needs.

Please let us know if it meets your needs.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Example Output

image


MACRO:   Use Date Calculator to Get Multilpe Dates [Example]

-~~~ VER: 2.1    2020-09-13 ~~~
Requires: KM 8.2.4+   macOS 10.11 (El Capitan)+
(Macro was written & tested using KM 9.0+ on macOS 10.14.5 (Mojave))

DOWNLOAD Macro File:

Use Date Calculator to Get Multilpe Dates [Example].kmmacros
Note: This Macro was uploaded in a DISABLED state. You must enable before it can be triggered.


ReleaseNotes

Author.@JMichaelTX

PURPOSE:

  • Use Date Calculator to Get Multilpe Dates
    • While KM provides extensive handling of dates using the ICU tokens & functions, it is very laborous to write a macro which calculates a new date from a date other than the current date.
    • The Action in this macro presents an alternative to using KM ICU tokens.
    • It provides one KM Action, a Shell Script with a Bash date command, to accomplishes this with only 5 lines, and yet is very configurable.
    • It only requires two inputs, which the macro author can enter as KM Variable Tokens in the Execute Shell Script Action Input area, which are Parameters for the script Standard In (stdin):
      • Base Date
      • Adjust by amount (in days, +/-)
    • By Default, the script uses this data, which can be easily overridden:
      • Adjust By Units: Days
      • Date Input Format: ISO 8601 YYYY-MM-DD
      • Date Output Format: ISO 8601 YYYY-MM-DD
      • Override these by adding Parameters to the Script Input area.
      • If you don't like the defaults, you can easily change the defaults in the script.

REQUIRES:

  1. KM 7+
  2. macOS 10.10+ (Yosemite)
    • However, it has been tested ONLY in KM 8.2.2 with macOS 10.12.6 :wink:

How To Use

As a Demo

  1. Just Trigger this macro.
    • Enter the Base Date and Offset
    • Observe Results

As a Reusable Action

  • Save the Execute Shell Script Action somewhere for easy reuse
    (choose one of these:)
    1. I recommend the KMFAM Macro System by @DanThomas
    2. Setup as a Sub-Macro, which can be called using an Execute Macro Action
    • Paste the Script Parameters as Parameters to the Execute Macro Action
    1. Store in a "template" macro where you can copy/paste into new Macros

MACRO SETUP

  • Carefully review the Release Notes and the Macro Actions
    • Make sure you understand what the Macro will do.
    • You are responsible for running the Macro, not me. ??
      .
  1. Assign a Trigger to this maro..
  2. Move this macro to a Macro Group that is only Active when you need this Macro.
  3. ENABLE this Macro.
    .
  • REVIEW/CHANGE THE FOLLOWING MACRO ACTIONS:
    (all shown in the magenta color)
    • Prompt for User Input
      • You can change the defaults for BaseDate and AdjustBy (which MUST include the sign), but do NOT change the Units.

This is great, thank you so much @JMichaelTX . I get the wrong week number for some reason, and I've seen the fix on the forum before, though I can't recall what's causing the problem.

The output says 09-14-2020 is in week 37, but Fantastical says it's week 38. Not sure which is correct. Do I need to account for time zone (US CDT), or because I have my weeks starting on Sunday instead of Monday, like some calendars? This site seems to confirm my calendar. Also did some digging here but not sure the "YYYY" vs "yyyy" vs "y" issue is relevant.

This script in the macro assumes Monday as the start of the week:

read myBaseDate

myDateFormatIn=${myDateFormatIn:-%Y-%m-%d}
# myDateFormatOut=+${myDateFormatOut:-%Y-%m-%d}
myDateFormatOut=+${myDateFormatOut:-"%W"}

date -j -f $myDateFormatIn "$myBaseDate" "$myDateFormatOut"

If you need Sunday, then just change the "%W" to "%w" in the myDateFormatOut line.

For more info see:
How To Format Date For Display or Use In a Shell Script

%U week number of year, with Sunday as first day of week (00..53)
%V ISO week number, with Monday as first day of week (01..53)
%w day of week (0..6); 0 is Sunday
%W week number of year, with Monday as first day of week (00..53)

In cases like that, I have found it is best to create a test macro with just the Action in question to test and verify it is working as expected.

Maybe I'm wrong, but if lower-case 'w' is day of the week, and upper-case 'W' is week number, those will give me two different values, no?

You are correct. It should be "%U".

OK, that part's working again, but I'm still getting week #43 for October 31, 2020, when my calendar says week #44. I like a puzzle, but this is driving me crazy. I'll keep digging.

Looks like

%V   	ISO week number, with Monday as first day of week (01..53)

will give you the desired week number.

1 Like

Yes, that does work. Bugs me as to why, since my calendar is set specifically to have Sunday as the first day, whether I choose Gregorian or ISO calendars. Same functionality with U and V in the macro, either way. Crazy. But it works. Sometimes the answer that looks wrong is actually the one that is most expedient. Therefore the hardest to find. Thanks again for your help!

@JMichaelTX thanks for the great help. Is there any way to adjust the language of the date output?
I have been looking around, but cannot find any solution.

It is bad since Mac Big Sur. I have seen in the "Region and Language" Setting one can add apps and adjust the language. However, Keyboard Maestro does not work since "Keyboard Maestro does not support other languages."

Is there are another way but to use search and replace?