Get all dates of a given week number

Hi,

Very often I need to calculate dates for filling documents with specific informations from our database.

Lately I got documents from a client, which only included the week number in their file name, not the first date of the week (e.g. ‘data_w19_analysis.indd’ vs. ‘data_230410_analysis.indd’).

So how to get the dates of a given week number to fill the documents?

Finally I came up with the solution below, which includes calling a Python script doing the date calculations.

To test the script, you will need to download the Python script and place it on your desktop.

The handler «getdatesforweeknum» offers several options to customize the output (first weekday, week number mode, etc.).

Happy scripting! :smiley:


property mytitle : "Dates of a Week Number"

-- 1. example: get all dates of a week
set yearstr to "2010"
set weeknumstr to "52"
set {weekdates, errmsg} to my getdatesforweeknum(yearstr, weeknumstr, missing value)
if weekdates is false then
	my dsperrmsg(errmsg, "--")
	return
else
	choose from list weekdates with prompt "Dates of the week " & weeknumstr & "/" & yearstr with empty selection allowed
end if

-- 2. example: Thursday of the given week
set {weekdates, errmsg} to my getdatesforweeknum(yearstr, weeknumstr, "3")
if weekdates is false then
	my dsperrmsg(errmsg, "--")
	return
else
	choose from list weekdates with prompt "Thursday of week " & weeknumstr & "/" & yearstr with empty selection allowed
end if


-- I am returning the dates of a certain week number in a given year
on getdatesforweeknum(yearstr, weeknumstr, weekdaynumstr)
	try
		-- firstweekday specifies the first day of the week
		-- "0" is Monday (the default), "6" is Sunday.
		set firstweekday to "6"
		-- "U":
		-- Week number of the year (Sunday as the first day of the week) as a decimal number [00,53].
		-- All days in a new year preceding the first Sunday are considered to be in week 0.
		--
		-- "W":
		-- Week number of the year (Monday as the first day of the week) as a decimal number [00,53].
		-- All days in a new year preceding the first Monday are considered to be in week 0.
		set weekmode to "U"
		-- "1": Monday is 1 and Sunday is 7
		-- "2": Monday is 0 and Sunday is 6
		set weekdaymode to "2"
		
		-- you can put the Python script wherever you want, just set
		-- the toolpath variable accordingly
		set toolpath to ((path to desktop as text) & "weeknums.py") as text
		set qtdtoolpath to quoted form of POSIX path of toolpath
		
		set command to "/usr/bin/python " & qtdtoolpath & " -y " & yearstr & " -f " & firstweekday & " -w " & weekmode & " -d " & weekdaymode
		set output to do shell script command
		set outputlines to paragraphs of output
		
		-- "1" -> "01"
		if length of weeknumstr is 1 then
			set weeknumstr to "0" & weeknumstr
		end if
		
		set weeknumdates to {}
		repeat with outputline in outputlines
			set {wnumstr, wnumdatestr, wdaynumstr} to my gettxtitems(tab, outputline)
			-- we found a matching week number
			if wnumstr is equal to weeknumstr then
				-- the user wants all seven dates of the week
				if weekdaynumstr is missing value then
					set weeknumdates to weeknumdates & wnumdatestr
				else
					-- the user just wants one specific date of the week
					if weekdaynumstr is equal to wdaynumstr then
						set weeknumdates to weeknumdates & wnumdatestr
					end if
				end if
			end if
		end repeat
		
		return {weeknumdates, missing value}
	on error errmsg
		return {false, errmsg}
	end try
end getdatesforweeknum

-- I am returning the text items of a text separated by the given delimiter
on gettxtitems(delim, txt)
	set olddelims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {delim}
	set txtitems to text items of txt
	set AppleScript's text item delimiters to olddelims
	return txtitems
end gettxtitems

-- I am indicating if a given item path exists
on itempathexists(itempath)
	try
		set itemalias to itempath as alias
		return true
	on error
		return false
	end try
end itempathexists

-- I am displaying error messages to the user
on dsperrmsg(errmsg, errnum)
	tell me
		activate
		display dialog "Sorry, an error occurred:" & return & return & errmsg & " (" & errnum & ")" buttons {"OK"} default button 1 with title mytitle with icon stop
	end tell
end dsperrmsg

Hi, Martin.

Here’s a vanilla date-arithmetic method. The output’s a list of AppleScript dates, but it’s a trivial matter to format them as text in your preferred style:

-- Assuming the ISO standard that weeks begin on Mondays and
-- that the first week of the year is the one containing 4th January,
-- although that might begin in the previous calendar year.

-- Easily adapted for other week-start conventions.

on getdatesforweeknum(yearNum, weekNum)
	set Jan4 to date "Tuesday 4 January 2000 00:00:00" -- Or 4th January in any year after 1582.
	set Jan4's year to yearNum -- Make that 4th January in the given year.
	set baseMonday to date "Monday 3 January 2000 00:00:00" -- Or any Monday in the past.
	
	-- Derive the beginning of the week containing 4th January in the given year.
	set week1Start to Jan4 - (Jan4 - baseMonday) mod weeks
	-- . and from that, the beginning of the weekNumth week.
	set weekNStart to week1Start + (weekNum - 1) * weeks
	
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set end of datesInWeek to weekNStart + i
	end repeat
	
	return datesInWeek
end getdatesforweeknum

getdatesforweeknum(2010, 52)

Hi Nigel,

Thank you very much for providing this pure AppleScript solution. I really admire your scripting skills, I would have never been able to write this code myself. Chapéu!

Best regards to UK,

Martin

Nigel is the absolutely unchallenged dominator of calendars and dates :wink: :cool:

You forgot family relationships :wink: He is simply fabulous!

Is this an in-joke between German speakers? :expressionless: Thanks anyway. (I think!) :slight_smile:

Here’s an adaptation of the vanilla code which takes a “week start” parameter (either an AppleScript weekday or a weekday name in English) and turns out the dates as dd.mm.yyyy texts.

-- Assuming the ISO standard that
-- the first week of the year is the one containing 4th January,
-- although that might begin in the previous calendar year.

on getdatesforweeknum(yearNum, weekNum, preferredWeekStart)
	set Jan4 to date "Tuesday 4 January 2000 00:00:00" -- Or 4th January in any year after 1582.
	set Jan4's year to yearNum -- Make that 4th January in the given year.
	set baseMonday to date "Monday 3 January 2000 00:00:00" -- Or any Monday in the past.
	set baseWeekday to baseMonday + ((offset of (text 1 thru 2 of (preferredWeekStart as text)) in "MoTuWeThFrSaSu") div 2) * days
	
	-- Derive the beginning of the week containing 4th January in the given year.
	set week1Start to Jan4 - (Jan4 - baseWeekday) mod weeks
	-- . and from that, the beginning of the weekNumth week.
	set weekNStart to week1Start + (weekNum - 1) * weeks
	
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set {day:d, month:m, year:y} to weekNStart + i
		tell y * 10000 + m * 100 + d as text
			set end of datesInWeek to text 7 thru 8 & "." & text 5 thru 6 & "." & text 1 thru 4
		end tell
	end repeat
	
	return datesInWeek
end getdatesforweeknum

getdatesforweeknum(2010, 52, Monday)

I’m getting a syntax error in 10.7.1

“Invalid date and time date Tuesday 4 January 2000 00:00:00.”

Any way to resolve it?

Hi, slashdot.

Just write both dates in your local format, probably date “January 4 2000” and date “January 3 2000”.

Thank Nigel for your help as always.

here’s the working code


on getdatesforweeknum(yearNum, weekNum)
	set Jan4 to date "Tuesday, January 4, 2000 12:00:00 AM" -- Or 4th January in any year after 1582.
	set Jan4's year to yearNum -- Make that 4th January in the given year.
	set baseMonday to date "Monday, January 3, 2000 12:00:00 AM" -- Or any Monday in the past.
	
	-- Derive the beginning of the week containing 4th January in the given year.
	set week1Start to Jan4 - (Jan4 - baseMonday) mod weeks
	-- . and from that, the beginning of the weekNumth week.
	set weekNStart to week1Start + (weekNum - 1) * weeks
	
	set datesInWeek to {}
	repeat with i from 0 to 6 * days by days
		set end of datesInWeek to weekNStart + i
	end repeat
	
	return datesInWeek
end getdatesforweeknum

getdatesforweeknum(2010, 52)