Apple Script: Can’t get date of “2018-12-12 10:00 AM”


Script Purpose
The script below uses an App called Pashua to display a custom dialog box that returns multiple inputs. These inputs are then used to create a new Calendar event.

enter image description here

The Issue The issue I am experiencing is that the date is returned in YYYY-MM-DD format. When the date is entered in MM/DD/YYYY format, the event is created with no problem.

How do I convert the date properly?

These are the lines of code that need help:

            set sDate to (sDate of theResult)
            --- Returns: 2018-12-12

            set sTime to (sTime of theResult)
            --- Returns: 10:00 AM

            set eDate to (eDate of theResult)
            --- Returns: 2018-12-12

            set eTime to (eTime of theResult)
            --- Returns: 11:00 AM

            set eStart to date of (sDate & space & sTime)
            --- Error: Can’t get date of 2018-12-12 10:00 AM

            set eEnd to date of (eDate & space & eTime)
            --- Error: Can’t get date of 2018-12-12 11:00 AM

This is the error that appears:

enter image description here

Entire Code:

 -- Get the path to the folder containing this script
 tell application "Finder"
set thisFolder to (container of (path to me)) as string
if "" exists then
    -- Looks like the Pashua disk image is mounted. Run from there.
    set customLocation to "⁨/Users/dnaab/Applications/"
    -- Search for Pashua in the standard locations
    set customLocation to "/Users/dnaab/Applications/"
end if
 end tell

    set thePath to alias (thisFolder & "Pashua.scpt")
    set pashuaBinding to load script thePath

tell pashuaBinding
    -- Display the dialog

        set pashuaLocation to getPashuaPath(customLocation)
        set dialogConfiguration to my getDialogConfiguration(pashuaLocation)
        set theResult to showDialog(dialogConfiguration, customLocation)

        -- Display the result. The record keys ("... of theResult") are defined in the
        -- dialog configuration string.
        if {} = theResult then
            display alert "Empty return value" message "It looks like Pashua had some problems using the window configuration." as warning
        else if cb of theResult is not "1" then

            set eCalendar to "Calendar"

            set eSummary to (eSummary of theResult)

            set eURL to (eURL of theResult)

            set eDescription to (eDescription of theResult)

            set sDate to (sDate of theResult)

            set sTime to (sTime of theResult)

            set eDate to (eDate of theResult)

            set eTime to (eTime of theResult)

            set sDate to date of (sDate & space & sTime)

            set eDate to date of (eDate & space & eTime)

            display dialog sDate buttons {"Cancel"} default button 1

            tell application "Calendar"
                tell calendar eCalendar
                    make new event with properties {summary:eSummary, start date:eStart, end date:eDate, url:eURL}
                end tell
            end tell
            -- The cancelbutton (named "cb" in the config string) was pressed

            display dialog "The dialog was closed without submitting the values"

        end if
    on error errorMessage
        display alert "An error occurred" message errorMessage as warning
    end try
end tell

 on error errStr number errorNumber
display dialog errStr
 end try

 -- Returns the configuration string for an example dialog
 on getDialogConfiguration(pashuaLocation)

if pashuaLocation is not "" then
    set img to "img.type = image
          img.x = 250
          img.y = 260
          img.maxwidth = 60
          img.tooltip = This is an element of type “image”
          img.path = /Applications/"
    set img to ""
end if

return "

 # Set window title
 *.title = New iCal Event

 # Event Summary
 eSummary.type = textfield
 eSummary.label = Event Summary
 eSummary.default = Calendar
 eSummary.width = 310
 eSummary.x = 1
 eSummary.y = 310

 # Add Start Date
 sDate.type = date
 sDate.label = Event Start Date
 sDate.default = today
 sDate.textual = 1
 sDate.x = 1
 sDate.y = 255

 # Add Start Time
 sTime.type = date
 sTime.label = Event Start Time
 sTime.default = today
 sTime.time = 1 = 0
 sTime.textual = 1
 sTime.width =70
 sTime.x = 110
 sTime.y = 255

 # Add End Date
 eDate.type = date
 eDate.label = Event Start Date
 eDate.default = today
 eDate.textual = 1
 eDate.x = 1
 eDate.y = 200

 # Add End Time
 eTime.type = textfield
 eTime.label = Event End Time
 eTime.width = 70
 eTime.x = 110
 eTime.y = 200

 # Add Calendar
 eURL.type = textfield
 eURL.label = URL
 eURL.default = message://
 eURL.width = 310
 eURL.x = 1
 eURL.y = 150

 # Description
 eDescription.type = textbox
 eDescription.label = Description
 eDescription.width = 310
 eDescription.x = 1
 eDescription.y =70

 # Add a cancel button with default label
 db.type = defaultbutton
 cb.type = cancelbutton
 end getDialogConfiguration

Best Answer

  • AppleScript dates are notoriously picky about format. They take their cue from your own system date & time settings, so even if I got a script to work properly on my system utilising a specific date & time format, it would probably not work on your system unless you happened to have the same macOS settings.

    Therefore, the best way to deal with AppleScript date objects is to create them from scratch using day, month, year and time components. That way, they work consistently across all systems, but, most importantly, allow you to manipulate them in your own script without unexpected errors.

    Add the following handler to the bottom of your script. It will give you the means to create an AppleScript date object by supplying to it the day, month and year, and (optionally) the hour, minute and second components:

    to makeASDate given year:y as integer ¬
        , month:m ¬
        , day:d as integer ¬
        , hours:h as integer : 0 ¬
        , minutes:min as integer : 0 ¬
        , seconds:s as integer : 0
        local y, m, d, h, min, s
        tell the (current date) to set ¬
            [ASDate, year, its month, day, time] to ¬
            [it, y, m, d, h * hours + min * minutes + s]
    end makeASDate

    To use it, simply call the handler like so:

    makeASDate given year:2018, month:January, day:23
        --> date "Tuesday, 23 January 2018 at 00:00:00"


    makeASDate given year:2018, month:1, day:23, hours:14, minutes:30, seconds:00
        --> date "Tuesday, 23 January 2018 at 14:30:00"

    Now, your next task is to extract the year, month a day components from your variables in order to pass them to the makeASDate handler. The easiest way to do this is by splitting your date/time variables into words. For example, with your start date and time:

    set [sy, sm, sd] to words of (sDate of theResult)
        --> {"2018", "12", "12"}
    set [sh, smin, AMPM] to words of (sTime of theResult)
        --> {"10", "00", "AM"}
    if AMPM = "PM" then set sh to sh + 12

    and similarly with your end times. I've illustrated a quick test with your time variable to determine whether or not it is AM or PM, and changed the value of the hour component accordingly (the makeASDate handler uses the 24-hour clock). You'll have to do another test with your date variable to determine what format the date is in: dd/mm/yyyy or yyyy-mm-dd, which might be as easy as:

    if (sDate of theResult) contains "-" then
        set [sy, sm, sd] to words of (sDate of theResult)
    else if (sDate of theResult) contains "/" then
        set [sd, sm, sy] to words of (sDate of theResult)
    end if