Date help - variables and referencing later

This seems like it should be very basic, but I'm stumped. In practice, there's more to what I want to do, but it boils down to.

  1. Prompt the user to enter a date (preferably something like: "Enter meeting date (mm/dd/yy):"
  2. Store that date in a variable
  3. Reference that variable to display/type the date in a variety of formats.

I've got the part where I can format a fixed date, but I haven't been able to get a variable to work.
image

Since "TIME()" is a function, as seen in your code snippet above, that implies that you can replace that function with a variable, like this:

%ICUDateTimeFor% MyVar %EEE, MMM d, yyyy%

The issue for you is probably the fact that when using variables to store dates that can work with functions, the variable must store the date in the "unixtime" format, not as an English phrase like "Mar 2, 2025."

The explanation for "unixtime" is explained (albeit briefly) at the top of this page:

https://wiki.keyboardmaestro.com/unixtime

Based on your original question, you are probably wondering how would you convert a string date into a "unixtime" date. You would do that using the token "ICUDateTimeFor" which is (briefly) explained here:

https://wiki.keyboardmaestro.com/token/ICUDateTime

So this is the short answer. See if this clarifies it. If not, we can write example code for you.

On the "ICUDateTime" Wiki page you'll see that %ICUDateTimeFor% requires the time to be in "unixtime" -- that means in "seconds since epoch".

It's generally preferable to store in seconds and format as required for use. You could also store the date, either in three variables or as a string, and use it as you did above -- but that is more difficult, mainly because you'll need to verify user input yourself to make sure it's a valid date.

So we'll do the first -- and using the "Date" field type in the "Prompt for User Input" action will let the user use their local date format while storing the value in seconds. It also, handily, gives the unixtime for 12 noon on that day -- which helps with time zone issues and similar.

So:

Get and Store Date as Seconds.kmmacros (4.6 KB)

Thanks @Airy & @Nige_S.

I wasn't aware of the default preset formats for user input. That solves that one.

I'm still having an issue with setting a variable to a human-readable date that I can manually enter in the macro — I didn't expect there to be a difference between user input and that version.

The macro I'm working on has some values that periodically change and some that change every time I run it. So for this one, it'll be easier for me to have actions right in the macro that set the variables.

I tried this, but couldn't get it to work with a separate %ICUDateTimeFor% function to convert to unixtime:
image

I even tried setting the value to exactly what I enter in the working TIME() function and then put the variable in the function instead, but wasn't successful there, either. (I'd skip the step of having the human-readable date in another variable, except that I need to format the same date different ways in different places — and the date regularly changes.)
image

image
image

I'd really appreciate if someone can point me to an example of a variable that starts with a human-readable date and then shows the exact steps to convert that to unixtime in a new variable.

Thanks,
Dave

The point is that you don't do that. Humans don't read variables -- your macro displays/outputs them in human-readable formats, just like mine above does in the "Display Text" action.

If you want to have an hard-coded variable that you sometimes edit to set to a new date, put that in your macro like you do above then immediately change it to seconds -- that way you are always working in seconds and know where you're at.

You can change your "yyyy/mm/dd"-format date into seconds with the (clunky, but single action):

CALCULATE(TIME(%Variable%Local_dateString[3]/%,%Variable%Local_dateString[1]/%,%Variable%Local_dateString[2]/%,12,0,0))

...as in:

date-string-to-seconds.kmactions (2.1 KB)

image

That's perfect!

Thanks so much, @Nige_S.

I've spent so much time on this and wouldn't have solved it without your help.

Another reason to stick with unixtime is that it's always guaranteed to be based on Greenwich Mean Time, while a data like "2025-2-2" is ambiguous because it doesn't specify which time zone. At any moment on earth there are two "dates" depending upon which time zone you are in.

1 Like

You were almost there -- just missing how to split the string into its "month", "day" and "year" parts to feed into the TIME() function.

Oh, and a bit of confusion about token evaluation. The way you were trying will work if you go via a "Filter: Process Tokens" action:

But that's some next-level stuff that quickly leads to % overload, and not as generally useful as splitting text into variables -- so let's spend a couple of minutes on text-splitting...

There's two easy ways to split text to variables -- treating the text as a psuedo array then access the array's elements by index, and the "Search using Regular Expression" action to pop chunks of your text straight into variables.

We used the pseudo array technique above, with "custom delimiters" to determine the text the elements should be split on. The default delimiter, used when you don't include a custom one, is , and your custom delimiter can be a longer string -- you can use =kmSep= to split "Hello=kmSep=World".

The general pattern is:

%Variable%variable-name[element-index-to-get]custom-delimiter%

Our text, in the variable Local_dateString, is of the form "month/day/year" so we can split on / to get three elements -- that's our custom delimiter. "month" is the first element so we can get that with

%Variable%Local_dateString[1]/%

...and, similarly

%Variable%Local_dateString[2]/%
%Variable%Local_dateString[3]/%

...will get us "day" and "year". Which we can then feed into the TIME() function, remembering that functions are Calculations and take variable names -- Local_month -- and not text tokens like %Variable%Local_month%.

Putting that all together:

Demo Date Array Split.kmmacros (4.7 KB)

Image

The regular expression version is much the same, except we can extract all three values in a single action using the regex

(\d+)/(\d+)/(\d+)

...where the first "capture group" is one-or-more consecutive (+) digits (\d) before the first / in our date string, the second is the digits between the two /s, the third is the digits after the second /:

image

Apart from that, this will look very similar to the last:

Demo Date Regex Split.kmmacros (4.4 KB)

Image

Hopefully that explains things so that you can use these methods in other macros -- string splitting is very useful, and very common, so have a play and get comfortable. And if I've confused more than helped -- shout!

1 Like