What I want to be able to do is have KBM prompt me for a date (ideally with a date picker), convert the text into a token (with above syntax) and then append that to a some text (I can figure that part out). I don’t know where to get started though even on the first two actions.
I'm generally not a big fan of date-pickers, although they can be very convenient at times.
The following AppleScript will take a text date written in various formats and output a formatted date-string of the type you're looking for.
For instance:
today tomorrow monday dec 7 jan 1
See the script for a few more...
If this method interests you we can turn it into something reasonably user-friendly.
-Chris
--------------------------------------------------------------------------------
# Auth: Christopher Stone { Heavey Lifting by Shane Stanley }
# dCre: 2016/08/26 13:30
# dMod: 2016/08/26 14:02
# Appl: AppleScriptObjC
# Task: Use Data-Detectors to find a date from a string and create a formatted date-string.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script, @Data_Detectors, @Find, @Date, @String, @Create, @Formatted, @DateString
--------------------------------------------------------------------------------
use framework "Foundation"
use scripting additions
--------------------------------------------------------------------------------
# For reference – today's date is 2016/08/26
set dateStr to "may 4"
set newDateStr to my getMyDateStringFrom:dateStr
--> "05-04-2017"
set dateStr to "4 may 1961"
set newDateStr to my getMyDateStringFrom:dateStr
--> "05-04-1961"
set dateStr to "may 4 1961"
set newDateStr to my getMyDateStringFrom:dateStr
--> "05-04-1961"
set dateStr to "today"
set newDateStr to my getMyDateStringFrom:dateStr
--> "08-26-2016"
set dateStr to "tomorrow"
set newDateStr to my getMyDateStringFrom:dateStr
--> "08-27-2016"
set dateStr to "sunday"
set newDateStr to my getMyDateStringFrom:dateStr
--> "08-28-2016"
set dateStr to "friday"
set newDateStr to my getMyDateStringFrom:dateStr
--> "09-02-2016"
--------------------------------------------------------------------------------
--» HANDLERS
--------------------------------------------------------------------------------
on formatDate:theDate usingFormat:formatString
if class of theDate is date then set theDate to my makeNSDateFrom:theDate
set theFormatter to current application's NSDateFormatter's new()
theFormatter's setLocale:(current application's NSLocale's localeWithLocaleIdentifier:"en_US_POSIX")
theFormatter's setDateFormat:formatString
set theString to theFormatter's stringFromDate:theDate
return theString as text
end formatDate:usingFormat:
--------------------------------------------------------------------------------
on getDatesIn:aString
set anNSString to current application's NSString's stringWithString:aString
set {theDetector, theError} to current application's NSDataDetector's dataDetectorWithTypes:(current application's NSTextCheckingTypeDate) |error|:(reference)
set theMatches to theDetector's matchesInString:anNSString options:0 range:{0, anNSString's |length|()}
set theDates to current application's NSMutableArray's array()
repeat with i from 1 to theMatches's |count|()
set thisMatch to (theMatches's objectAtIndex:(i - 1))
(theDates's addObject:(thisMatch's |date|()))
end repeat
return theDates as list
end getDatesIn:
--------------------------------------------------------------------------------
on getMyDateStringFrom:dateStr
set dateList to my getDatesIn:dateStr
if length of dateList = 0 then
error "No dates were returned from the given string!"
else if length of dateList = 1 then
set dateStr to item 1 of dateList
set dateString to my formatDate:dateStr usingFormat:"MM-dd-Y"
else if length of dateList > 1 then
error "Too many dates were found in the given string!"
end if
return dateString
end getMyDateStringFrom:
--------------------------------------------------------------------------------
on makeNSDateFrom:theASDate
set {theYear, theMonth, theDay, theSeconds} to theASDate's {year, month, day, time}
if theYear < 0 then
set theYear to -theYear
set theEra to 0
else
set theEra to 1
end if
set theCalendar to current application's NSCalendar's currentCalendar()
set newDate to theCalendar's dateWithEra:theEra |year|:theYear |month|:(theMonth as integer) ¬
|day|:theDay hour:0 minute:0 |second|:theSeconds nanosecond:0
return newDate
end makeNSDateFrom:
--------------------------------------------------------------------------------
Dan - that GUI looks great but reading that post and see that it is a bit above my head.
Ccstone - this would be a natural language parser right? I could say Tuesday, 1 week, or something and it returns the date? That would be pretty incredible and if it can be done inside KBM (vs outside apple scripts etc) sounds ideal/clean.
Feed it any kind of date-string Apple Data Detectors understands, and it will spit out your preferred format date-string.
today
tomorrow
Friday
1 jan 2020
…
Here's an uber-simple parser that understands the format:
today + <number> <days, months, or years>
--------------------------------------------------------------------------------
# Auth: Christopher Stone
# dCre: 2016/08/28 15:56
# dMod: 2016/08/28 15:56
# Appl: Miscellaneous
# Task: Parse a natural language string into a date.
# Libs: None
# Osax: None
# Tags: @Applescript, @Script,
--------------------------------------------------------------------------------
# A sample date specifier
--------------------------------------------------------------------------------
set dateStr to "today + 7 weeks"
# Understands days, weeks, years
--------------------------------------------------------------------------------
# Process the specifier into a valid date string.
--------------------------------------------------------------------------------
if dateStr contains "today" then
set theDate to current date
set time of theDate to 12 * hours -- workaround for dst
set newDateStr to date string of theDate
end if
if dateStr contains "+" then
set AppleScript's text item delimiters to "+ "
set dateOptions to text item 2 of dateStr
set numOpt to word 1 of dateOptions
set multOpt to word 2 of dateOptions
end if
set theScript to "(date \"" & newDateStr & "\") + " & numOpt & " * " & multOpt
set parsedDate to run script theScript
set time of parsedDate to 12 * hours
return date string of parsedDate
--------------------------------------------------------------------------------
There are a number of things I'd do to make this more capable and robust, but all that takes time.