Date calculation in AppleScript. Week numbers and their start date

applescriptomnifocus

I want to write an AppleScript that creates projects in OmniFocus where their defer date and due date is set to any weeks' start and end day.

The result should look like this:

weeknumber: day1. month1. year1 - day2. month2. year2

Where weeknumber is replaced with a weeks' week number. day1, month1 and year1 take weeknumbers' week number and parse it to that days' date. So for week number 09 in 2016 that would be 29. 02. 2016. The first week ends (day2 and so forth) end on 06. 02. 2016. So the result for the first week of 2016 would look like this:

09: 29. 02. 2016 - 06. 02. 2016

From the shell it is possible to get the last day of a month like so:

date -v 1d -v 3m -v 16y -v -1d +'%V: %d. %m. %Y'
09: 29. 02. 2016

In AppleScript you can turn any string, e.g. returned from a shell script (date) into a date object with the syntax:

set lastDayShell to do shell script "date -v 1d -v 3m -v 16y -v -1d +'%V: %d. %m. %Y'"
set lastDay to date lastDayShell

The command to add a new project to OmniFocus is this:

tell application "OmniFocus"
    tell default document
        set weekNumbers to folder "Week Numbers"
        tell weekNumbers
            set project1 to make new project with properties {name:"09: 29. 02. 2016", defer date:firstDay, due date:lastDay, singleton action holder:true}
        end tell
    end tell
end tel

I know all of that. I just can't find a resource that says how to get the first and last day of any week. I want to set the defer date of any weeks' start to the first of the week, and the due date to the last day.

Best Answer

Thanks to @ryan-m's comment I found a solution. Turns out date(1) is actually really cool. Its ability to do "adjustments" were the answer.

You can tell date to simply "go to" a specific day by using -v. You can then use plus and minus to "adjust" that date in another -v. So for instance:

date -v 1w -v 16y

Will go to the first month of 2016. (Or a date that contains that date)

With an adjustment we can walk through dates:

date -v +1w -v +0d -v 16y
date -v +1w -v +6d -v 16y

This goes to the first week of 2016. The second command goes from the beginning of that first week 6 days ahead. This is the 10th of January 2016. -v +2w would be the second week, and so forth. It's apparent which part can be automated here.

Everything that +'string' at the end does is it formats the date you're at in the way you want it displayed. I use this in my script to make a date-string that AppleScript's date command understands. Please don't confuse the shell command date(1) with the AppleScript date command.

This is the script I ended up with, by the way:

repeat with weekNumber from 1 to 52
    set weekStartShell to (do shell script "date -v +" & weekNumber & "w -v +0d -v 16y +'%d. %m. %Y'")
    set weekStart to date weekStartShell
    set weekEndShell to do shell script "date -v +" & weekNumber & "w -v +6d -v 16y +'%d. %m. %Y'"
    set weekEnd to date (weekEndShell & " 23:59:59")
    set projectName to (("CW" & weekNumber & ": " & weekStartShell & " - " & weekEndShell) as string)

    tell application "OmniFocus"
        tell folder "Day Projects" of default document
            set projectWeek to make new project with properties {name:projectName, defer date:weekStart, due date:weekEnd, singleton action holder:true}

        end tell
    end tell

end repeat

Note that in order to use AppleScript's set var to date "date-string" you have to give it a string in your locale. In Europe the string is 01. 02. 2016 23:59:59. In America this probably is something like 2016/02/01 23:59:59. You need to modify these in the variables in the script. (+'%Y/%m/%d' at the end)