首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在没有到期日(或今天到期)的情况下完成提醒,而不创建虚拟提醒?

问如何在没有到期日(或今天到期)的情况下完成提醒,而不创建虚拟提醒?
EN

Stack Overflow用户
提问于 2022-07-12 16:59:50
回答 1查看 104关注 0票数 0

我正在尝试编写一个AppleScript,以完成与名称和列表匹配的所有提醒,但如果它们要么没有到期日,要么过期了(到期日<今天)。

我知道我可以循环使用提醒来解决这个问题,但是当有大量提醒时,循环提醒会非常缓慢,所以我想知道如何在一行中完成这个任务,这在我的用例中是多个数量级的。

当我运行这个脚本时:

代码语言:javascript
复制
set curDate to current date
tell application "Reminders"
    set myList to "Reminders"
    set myTitle to "Test 1"
    set completed of every reminder in list myList whose completed is false and name is myTitle and (due date is missing value or due date is less than curDate) to true
end tell

我知道这个错误:

代码语言:javascript
复制
error "Reminders got an error: Can’t make missing value into type date." number -1700 from missing value to date

这句话的重点是:

代码语言:javascript
复制
set completed of every reminder in list myList whose completed is false and name is myTitle and (due date is missing value or due date is less than curDate) to true

我似乎无法让type of due date和missing value的类型匹配,除非创建一个虚拟提醒。注意:以下代码工作正常

代码语言:javascript
复制
set curDate to current date
tell application "Reminders"
    set myList to "Reminders"
    set myTitle to "Test 1"
    -- Create a dummy reminder whose due date is "missing value"
    set newremin to make new reminder
    set name of newremin to "Debugging delete me"
    set completed of every reminder in list myList whose completed is false and name is myTitle and (due date is (due date of newremin) or due date is less than curDate) to true
end tell

我创建了两个提醒来测试这一点,两者都被命名为"Test 1“。一个是今天到期的,另一个是没有到期日的。使用虚拟提醒的工作示例成功地完成了这两个提醒,并且运行速度相对较快。

是否有一种方法可以修改1 set completed...行来工作,而不必创建一个虚拟提醒?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-07-15 14:59:29

更新答复

我的第一个答案有一个问题,我想出来了。无论是我的脚本还是另一个答案中的脚本,都不会完成提醒程序中显示为未完成的提醒。我认为这要么是由于一个提醒同步问题(多个设备之间),要么是因为我完成了然后“未完成”的提醒,其中任何一个都会导致重复提醒。

不管原因如何,在这种情况下,every reminder...语句只将搜索条件与一个(而不是提醒程序显示的标准)进行比较。下面的屏幕记录显示,AppleScript从不在提醒应用程序中显示的当前到期提醒上循环:

https://drive.google.com/open?id=1S0ToJcMK7o5wOspwOG_eIVIJ1xowA6fg&authuser=hepcat72%40gmail.com&usp=drive_fs

奇怪的是,那些重复出现的“未来到期”提醒确实会得到评估和返回。我发现,如果我返回每个提醒并搜索结果,我就会发现一个重复的提醒,其到期日与提醒程序中显示的不完整的提醒相匹配,但是返回的提醒的属性显示它是完整的。

此外,给定whose due date is greater than curDate的脚本只返回将来到期的定期提醒,如果在重复中的提醒已经完成,那么“未完成”。

另一个有趣的/奇怪的行为是,如果我不包括whose due date is...,大约一年后返回的一个不完整的提醒显示是到期的,我在实际的sqlite3数据库中找不到这样的提醒。

无论如何,我发现的唯一对这些提醒数据库不一致既快速又健壮的解决方案是从sqlite3数据库中获取提醒ID,并在这些提醒ID上在AppleScript中循环。

我编写了一个perl脚本,用于在sqlite3数据库中找到提醒,尽管我还没有公开发布它。但是,如果您编写了自己的脚本,这里有一个屏幕记录证明,说明要返回什么以及如何使用提醒ID来完成提醒:

https://drive.google.com/open?id=1S2WEyhUiL9CsyWcfFCvJ0CV7OqLqtAO2&authuser=hepcat72%40gmail.com&usp=drive_fs

我最终将发布我的perl脚本,并且我将尝试在我发布的时候更新这个答案,但是我会说,我得到的AppleScript/PerlScript组合体(到目前为止)似乎总是完成了向它抛出的每一个预期的提醒,不过我将添加一个警告,如果另一个设备的sqlite3数据库在它的sqlite3数据库中有不同的in集,除非它在该设备上运行,否则这个脚本无法完成这些。

同时,下面是我的AppleScript的内容(为简洁而编辑),它显示了对perl脚本的调用:

代码语言:javascript
复制
set status to my completeReminder("Feed the cat", "Reminders")

on completeReminder(myTitle, myList)
    
    set curDate to current date
    
    set fcmd to "perl getReminder.pl -c incomplete -t '" & myTitle & "' -l '" & myList & "' -d future-due --ids"
    set ccmd to "perl getReminder.pl -c incomplete -t '" & myTitle & "' -l '" & myList & "' -d past-or-no-due --ids"
    
    try
        set future_due to paragraphs of (do shell script fcmd)
        set to_complete to paragraphs of (do shell script ccmd)
    on error errmsg
        return {-1, errmsg}
    end try
    
    if (count of to_complete) is equal to 0 then
        return {0, "No matching reminders"}
    end if
    
    if (count of future_due) is greater than 0 then
        -- Version to avoid completing future-due reminders
        try
            with timeout of 600 seconds
                tell application "Reminders"
                    repeat with remid in to_complete
                        set rems to (every reminder whose id is remid)
                        repeat with rem in rems
                            set rem to item 1 of rems
                            set completed of rem to true
                        end repeat
                    end repeat
                end tell
            end timeout
        on error errmsg
            return {-1, errmsg}
        end try
    else
        -- This may or may not actually be faster than the loop using the IDs above - I did not make that comparison, but it was much faster in my previous versions
        tell application "Reminders"
            set completed of every reminder in list myList whose completed is false and name is myTitle to true
        end tell
    end if
    return {(count of to_complete), (count of to_complete) & " reminder(s) completed"}
end completeReminder

旧答案

虽然我还没有想出一种在1行中这样做的方法,但我确实注意到,速度是我希望在1行中这样做的原因,结合另一个答案,我找到了一种解决方案,它的运行速度是使用1行every reminder语句所能达到的速度的2倍,而不需要创建虚拟提醒。

即使使用我的虚拟提醒1行解决方案,我也测试发现,花了一分钟时间才完成的是虚拟提醒创建。1行语句的速度非常快,一旦它有虚拟的提醒,比较一个“缺失的值到期日”与任何到期日的提醒。

我也试图寻找一个现有的虚拟提醒,但仍然,它运行了超过一分钟的时间。我怀疑这是every reminder语句返回的要求,这是一个限制时间的瓶颈。但是,通过更多的测试,我发现我可以快速(大约是7秒)执行一个执行返回的first reminder语句。

我还意识到,我所要做的就是避免完成在未来的中到期的提醒,所以我能够将它与一个first reminder语句结合起来,以确定是否确实存在我不想根据到期日完成的匹配提醒。结果是下面的脚本,它在大约13秒内完成了2次提醒(无到期日和过期到期日)(当没有明确不应该完成的提醒时)。最糟糕的情况是,如果有避免完成的提醒,它将在@Robert Kniazidis的解决方案( 1m30s到2m30s之间)加上7秒内运行:

代码语言:javascript
复制
set curDate to current date
set myList to "Reminders"
set myTitle to "Test 1"
tell application "Reminders"
    try
        -- If no reminders with due dates to avoid exist, this errors out with an index error on the first line and we can complete every matching reminder regardless of due date in the catch. Otherwise, we continue on with a slow solution...
        first reminder in list myList whose completed is false and name is myTitle and due date is greater than curDate
        
        -- If there are reminders to avoid completing, do the slow roll...
        try
            with timeout of 600 seconds
                set theReminders to reminders of list myList whose completed is false and name is myTitle
                repeat with theReminder in theReminders
                    try
                        set dueDate to (due date of theReminder) as date
                        if dueDate is less than curDate then set completed of theReminder to true
                    on error
                        set completed of theReminder to true
                    end try
                end repeat
            end timeout
        on error errmsg
            return errmsg
        end try
    on error
        -- Complete every matching reminder regardless of due date (very fast)
        set completed of every reminder in list myList whose completed is false and name is myTitle to true
    end try
end tell

这是一个屏幕记录,显示它的运行时间约为13s (与另一种解决方案相比,后者需要1m30s到2m30s)。

https://drive.google.com/open?id=187J4PV0qM9fB8ycdVoZBqjtBqAmYDBh2&authuser=hepcat72%40gmail.com&usp=drive_fs

注意,如果代码的慢部分出现超时错误,则返回错误字符串。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/72955922

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档