While you're waiting for a bug fix, I thought I'd offer a few remarks and recommendations regarding your AppleScript:
1)
Be mindful about setting text item delimiters
prior to performing any list → string
coercion
It's always advisable to ensure you explicitly set the value of the text item delimiters
to something useful or something benign before coercing a list
into a string
. characters of...
produces a list
of characters. Since text item delimiters
is a top-level AppleScript property, its value is a global environment value that persists for the lifetime of any single AppleScript process, and so will apply to any script that gets executed in that AppleScript instance. Script Editor instantiates a brand new process for different scripts and also for every newly compiled version of a single script, which allows execution to occur inside a fresh, unpolluted environment where this issue with text item delimiters
will very rarely be seen. However, a lot of widely-used AppleScript runners still instantiate a single AppleScript process at application launch, and then re-use this one, shared environment to run each and every AppleScript within up until the point at which the application is quit. Namely, FastScripts, Keyboard Maestro, Alfred, and I imagine BTT all do this (although the upcoming release of FastScripts I believe will execute separate scripts in separate environments, but multiple executions of any single script will take place inside a single instance). Therefore, just try and be mindful about not polluting the global (top-level) namespace in your scripts (which is good advice to follow in any language that scopes its variables and functions); and be diligent with managing properties such as text item delimiters
that can be set by one script and then later inadvertently have unintended effects applied to another script.
In this case, you can simply set the value of text item delimiters
to something benign in the first line of your handler—benign being either an empty string (""
), or an empty list ({}
), meaning concatenation of list
items can occur without the additional insertion of any delimiting characters:
on getTimeInHoursAndMinutes()
set the text item delimiters to {}
.
.
.
set theHour to characters 1 thru (Pos - 1) of timeStr as string
set timeStr to characters (Pos + 1) through end of timeStr as string
.
.
.
2)
Setting text item delimiters
to something useful
This line appears twice in your handler, which means you had to perform the same sequence of operations twice over in order to extract your hour value, and then your minute value. You can do this in a single set of operations, using text item delimiters
. In addition to being involved in joining list
items together when coercing to a string
, they are involved in the opposite action where a string
is split into a list
of text items
at the occurrence of any of the delimiters you specify.
To demonstrate, I'll use the ISO-8601 international standard format for date-time strings, as it uses colons to separate the time components, which you evidently do as well. Additionally, it uses hyphens to separate the date components, and the character "T" to delimit the start of the time string portion of the date-time string. Therefore, those are the delimiters I'll want to use for this task, which will allow me to extract the hour and minute values in a single line:
set now to "2021-06-16T05:44:01" --> ISO-8601 formatted date/time
set the text item delimiters to {":", "-", "T"}
get the text items of now --> {"2021", "06", "16", "05", "44", "01"}
get {hours:text item -3, minutes:text item -2} of now
--> {hours:"05", minutes:"44"}
return the contents of the result's {hours, minutes} as text
--> "05:44"
I put the hours and minutes into a list
and coerced that into a string
(well, text
—same thing) to demonstrate the concatenation process under text item delimiters
I had already set. I specifically made the first delimiter in the list the colon, as that is the one that gets used to join the items of a list
together.
3)
If you can avoid a list → string
coercion, avoid it
characters of...
results in a list
class object, that necessitates your subsequent coercion back into a string
. I also just did a similar thing above using text items
instead of characters
, which still needed to be coerced back to a string. Besides the text item delimiters
trap that can be bothersome when it's not being useful, coercing values from one type class to another is a pretty expensive operation in any situation, but list
objects are also one the most complex data structures AppleScript has. Whilst we can't avoid doing any coercions whatsoever (since you require a string
value by the end, but we start with a date
object), we can avoid using lists as a middle man, which spares us confronting the aforementioned inconveniences.
Instead of grabbing individual letters, we can grabbing a whole slice of text
, i.e. a substring. Assuming your hour and minutes form a continuous substring within your time string
, then we can splice it out as a single chunk of text in much the same way as you were able to target a specific character range with characters 1 thru...
:
tell the (current date) as «class isot» ¬
as string to return text 12 thru 16
--> "06:25"
Done. That can be your entire handler, in a single line. It makes use of the handy type class known only as «class isot»
, which I suppose is short for ISO-(8601)-standard time, or so-called "iso-time", which returns the date ()that must be coerced into a string
), where upon doing so, it will be formatted according to the ISO-8601 standard, i.e. "2021-06-16T06:25:34"
. This time, rather than use text item delimiters
, I just took the characters between positions 12 and 16, except they were extracted as a single, unary string value that is already colon-delimited, so serves your needs ideally.
4)
Although, this is how I would actually choose to do it
to getTimeInHoursAndMinutes()
tell the (current date) ¬
to return "" & ¬
(its hours) & ¬
":" & (its minutes)
end getTimeInHoursAndMinutes
No list → string
coercions, no text item delimiters
, and no manipulation of characters or substrings.