2 votos

Apple script: No se puede obtener la fecha de "2018-12-12 10:00 AM"

script Objetivo El script siguiente utiliza una App llamada Pashua para mostrar un cuadro de diálogo personalizado que devuelve múltiples entradas. Estas entradas se utilizan para crear un nuevo evento del Calendario.

enter image description here

El tema El problema que tengo es que la fecha se devuelve en formato AAAA-MM-DD. Cuando la fecha se introduce en formato MM/DD/AAAA, el evento se crea sin problemas.

¿Cómo puedo convertir la fecha correctamente?

Estas son las líneas de código que necesitan ayuda:

            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

Este es el error que aparece:

enter image description here

Código completo:

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

0 votos

Qué código devuelve la fecha en YYYY-MM-DD ¿formato? Por favor, incluya el código correspondiente para que podamos probarlo nosotros mismos.

0 votos

He añadido el código.

0 votos

Wow, buen trabajo, y ahora lo acabas de publicar

1voto

qarma Puntos 71

Las fechas de AppleScript son notoriamente exigentes con el formato. Se basan en la configuración de la fecha y la hora de tu sistema, así que incluso si consiguiera que un script funcionara correctamente en mi sistema utilizando un formato de fecha y hora específico, probablemente no funcionaría en tu sistema a menos que tuvieras la misma configuración de MacOS.

Por lo tanto, la mejor manera de tratar con los objetos de fecha de AppleScript es crearlos desde cero utilizando componentes de día, mes, año y hora. De esta forma, funcionan de forma consistente en todos los sistemas, pero, sobre todo, te permiten manipularlos en tu propio script sin errores inesperados.

Añade el siguiente manejador al final de tu script. Le proporcionará los medios para crear un objeto de fecha AppleScript suministrándole el día, el mes y el año, y (opcionalmente) los componentes de hora, minutos y segundos:

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

Para utilizarlo, basta con llamar al manipulador de esta manera:

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"

Ahora, su siguiente tarea es extraer los componentes de año, mes y día de sus variables para pasarlos al makeASDate manipulador. La forma más fácil de hacerlo es dividiendo sus variables de fecha/hora en palabras. Por ejemplo, con su fecha y hora de inicio:

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

y de manera similar con sus tiempos finales. He ilustrado una prueba rápida con su variable de tiempo para determinar si es o no AM o PM, y he cambiado el valor del componente de la hora en consecuencia (el makeASDate utiliza el reloj de 24 horas). Tendrás que hacer otra prueba con tu variable de fecha para determinar en qué formato está la fecha: dd/mm/yyyy o yyyy-mm-dd que podría ser tan fácil como:

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

Anonymous Coder Puntos 23

Lo que dijo @CJK - tratar de cocinar una cadena de fecha es una batalla perdida porque depende de la configuración del usuario, utilice los componentes en su lugar - excepto que su controlador no siempre funciona. Si lo ejecuta en un día con un número mayor que el número de días del mes de la entrada, el resultado será el mes después de el que usted pidió. Por ejemplo, si pide "mes:2 día:15" el 31 de enero, obtendrá el 15 de marzo, no el 15 de febrero. Hay tres factores implicados, ninguno de los cuales parece estar explícitamente documentado:

  1. AppleScript date los objetos se almacenan como un punto absoluto en el tiempo, no como un conjunto de componentes. (Bueno, sobre todo absolutos: por razones históricas, son relativos a la zona horaria actual). Los componentes se sintetizan bajo demanda a partir de ese punto en el tiempo utilizando el calendario actual.

  2. Fijar un componente, como por ejemplo set month of d to April significa que descompone la fecha en componentes, cambia un componente y luego los vuelve a componer en un punto en el tiempo. No se especifica qué ocurre si uno de los componentes está fuera de rango, pero en la práctica, un día fuera de rango se envolverá en algún mes siguiente. Considere, continuando con el ejemplo, set day of d to 41 . El 41 de abril es, lógicamente, 11 días después del último día de abril, el 30 de abril, por lo que se obtiene el 11 de mayo.

  3. Incluso cuando se utiliza la sintaxis del conjunto de patrones set {x, y} to {1, 2} Las asignaciones se hacen de una en una. (La documentación https://developer.apple.com/library/archive/documentation/AppleScript/Conceptual/AppleScriptLangGuide/reference/ASLR_cmds.html#//apple_ref/doc/uid/TP40000983-CH216-SW52 los describe como "simultáneos", ya que set {x, y} to {y, x} de hecho intercambia x y y pero eso no es del todo correcto: lo que realmente ocurre es que primero evalúa todas las expresiones, almacenando los resultados en temporales implícitos, y luego asigna los temporales a las variables de una en una. Todas las evaluaciones ocurren antes de todas las asignaciones, pero el orden no está especificado).

Así que, digamos que ejecutas esto el 31 de enero de 2020:

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

Lo que ocurre es que:

  1. set ASDate to (current date) . ASDate es el 31 de enero de 2020 a la hora actual.
  2. set year of ASDate to 2018 . La fecha del ASD es ahora el 31 de enero de 2018.
  3. set month of ASDate to 2 . Los componentes especifican el 31 de febrero de 2018, que no existe, por lo que se envuelve: d es ahora el 3 de marzo de 2018.
  4. set day of ASDate to 15 . d es ahora el 15 de marzo de 2018, no el 15 de febrero como pediste.

Hay dos maneras de evitarlo: una es establecer primero el day y month en ese orden a 1 primero, y luego aplicar los parámetros de entrada. La otra es utilizar una fecha fija con un mes y un día de baja numeración, digamos "1/1/1904", en lugar de current date como punto de partida. Un manejador corregido podría tener este aspecto:

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

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X