# Date calculation in AppleScript. Week numbers and their start date

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.

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)

I believe this should get you what you want, assuming to you want the first Saturday of a given month.

First, let's start with getting your last day of the month with the script you used, but output as UNIX time.

START=$(date -v 1d -v 3m -v 16y -v -1d +'%s') # given date in seconds  Now we can find the first Saturday of the month with this date. # parse the given date time # move to the first of the month (-v1d) # move to the 6th day of the week (-v6w) date -v1d -v6w -jf '%s'$START '+ %a %d %b % Y'

# Result: Sat 06 Feb 2016

• Thank you for the help, Ryan! That didn't actually answer my question, but it gave me a nudge in the right direction. I'll post my answer when I finished the script. – Zettt Dec 28 '15 at 18:33