2 votes

Apple script : Impossible d'obtenir la date de "2018-12-12 10:00 AM"

script Objectif Le script ci-dessous utilise une App appelée Pashua pour afficher une boîte de dialogue personnalisée qui renvoie plusieurs entrées. Ces entrées sont ensuite utilisées pour créer un nouvel événement du calendrier.

enter image description here

La question Le problème que je rencontre est que la date est renvoyée au format AAAA-MM-JJ. Lorsque la date est saisie au format MM/JJ/AAAA, l'événement est créé sans problème.

Comment convertir correctement la date ?

Ce sont les lignes de code qui ont besoin d'aide :

            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

Voici l'erreur qui apparaît :

enter image description here

Code entier :

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

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

tell pashuaBinding
    -- Display the dialog

    try
        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
        else
            -- 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/Calendar.app/Contents/Resources/App.icns"
else
    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
 sTime.date = 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

1voto

OnePablo Points 1

Les dates AppleScript sont notoirement pointilleuses en matière de format. Elles se basent sur les paramètres de date et d'heure de votre propre système, donc même si je parvenais à faire fonctionner correctement un script sur mon système en utilisant un format de date et d'heure spécifique, il ne fonctionnerait probablement pas sur votre système à moins que vous n'ayez les mêmes paramètres MacOS.

Par conséquent, la meilleure façon de traiter les objets date AppleScript est de les créer de toutes pièces en utilisant les composants jour, mois, année et heure. De cette façon, ils fonctionnent de manière cohérente sur tous les systèmes, mais, plus important encore, vous permettent de les manipuler dans votre propre script sans erreurs inattendues.

Ajoutez le gestionnaire suivant au bas de votre script. Il vous donnera les moyens de créer un objet date AppleScript en lui fournissant le jour, le mois et l'année, et (facultativement) les composantes heure, minute et seconde :

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]

    ASDate
end makeASDate

Pour l'utiliser, il suffit d'appeler le gestionnaire comme suit :

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

o

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

Maintenant, votre prochaine tâche est d'extraire les composants année, mois et jour de vos variables afin de les passer à la fonction makeASDate manipulateur. Le moyen le plus simple d'y parvenir est de diviser vos variables de date/heure en mots. Par exemple, avec votre date et heure de début :

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

et de même avec votre fin des temps. J'ai illustré un test rapide avec votre variable d'heure pour déterminer s'il s'agit de AM ou de PM, et j'ai modifié la valeur de la composante horaire en conséquence (le paramètre makeASDate utilise l'horloge de 24 heures). Vous devrez effectuer un autre test avec votre variable de date pour déterminer le format de la date : dd/mm/yyyy o yyyy-mm-dd ce qui pourrait être aussi simple que :

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

1voto

Chris N Points 136

Ce que @CJK a dit -- essayer de préparer une chaîne de date est une bataille perdue d'avance car cela dépend des paramètres de l'utilisateur, utilisez plutôt les composants -- sauf que leur gestionnaire ne fonctionne pas toujours. Si vous l'exécutez sur un jour dont le numéro est supérieur au nombre de jours du mois de l'entrée, le résultat sera le mois après celui que vous avez demandé. Par exemple, si vous demandez "month:2 day:15" le 31 janvier, vous obtiendrez le 15 mars et non le 15 février. Trois facteurs entrent en jeu, dont aucun ne semble être explicitement documenté :

  1. AppleScript date les objets sont stockés comme un point absolu dans le temps, et non comme un ensemble de composants. (Enfin, surtout absolu : pour des raisons historiques, ils sont relatifs au fuseau horaire actuel). Les composants sont synthétisés à la demande à partir de ce point dans le temps en utilisant le calendrier actuel.

  2. Le réglage d'un composant, tel que set month of d to April Cela signifie qu'il décompose la date en éléments, modifie l'un de ces éléments, puis les recompose en un point dans le temps. Ce qui se passe si l'un des composants est hors de la plage n'est pas spécifié, mais en pratique, un jour hors de la plage sera enveloppé dans un mois suivant. Considérons, en continuant l'exemple, set day of d to 41 . Le 41 avril est, logiquement, 11 jours après le dernier jour d'avril, le 30 avril, ce qui donne le 11 mai.

  3. Même en utilisant la syntaxe du jeu de motifs set {x, y} to {1, 2} les affectations se font une par une. (La documentation https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html#//apple_ref/doc/uid/TP40000983-CH216-SW52 les décrit comme "simultanées", puisque set {x, y} to {y, x} échange en effet x y y mais ce n'est pas tout à fait exact : ce qui se passe réellement, c'est qu'il évalue d'abord toutes les expressions, en stockant les résultats dans des temporaires implicites, puis affecte les temporaires aux variables une par une. Toutes les évaluations se produisent avant toutes les affectations, mais l'ordre n'est pas spécifié par ailleurs).

Supposons donc que vous exécutez ce programme le 31 janvier 2020 :

makeASDate given year:2018, month:2, day:15

Ce qui se passe, c'est que :

  1. set ASDate to (current date) . ASDate correspond au 31 janvier 2020, quelle que soit l'heure actuelle.
  2. set year of ASDate to 2018 . L'ASDate est maintenant le 31 janvier 2018.
  3. set month of ASDate to 2 . Les composants précisent le 31 février 2018, qui n'existe pas, donc cela s'enroule : d est maintenant le 3 mars 2018.
  4. set day of ASDate to 15 . d est maintenant le 15 mars 2018, et non le 15 février comme vous l'aviez demandé.

Il y a deux façons de contourner ce problème : la première consiste à définir d'abord l'option day y month dans cet ordre à 1 d'abord, puis appliquer les paramètres d'entrée. L'autre solution consiste à utiliser une date fixe avec un mois et un jour à faible numérotation, par exemple "1/1/1904", au lieu de current date comme point de départ. Un gestionnaire corrigé pourrait ressembler à ceci :

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, p

    set p to "1/1/1904"
    tell the (date p) to set ¬
        {ASDate, year, its month, day, time} to ¬
        {it, y, m, d, h * hours + min * minutes + s}

    ASDate
end makeASDate

LesApples.com

LesApples est une communauté de Apple où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres utilisateurs d'appareils Apple, poser vos propres questions ou résoudre celles des autres.

Powered by:

X