Calculating due dates

I have a script that needs to print a due date that is 3 months ahead of a selected date. Have looked at Applescript’s date routines, you can add days but not months so produced some long winded code to accomplish this. Then discovered the Unix command date which allows month addition but only on the current date. Is it possible to add a variable to the date command, my Unix knowledge is very minimal.
Any help or guidance gratefully received!

set threeMonths to do shell script “date -v +3m +‘%d/%m/%Y’” – 3 month expiry date

NSCalendar of the Foundation framework can do it for you

use AppleScript version "2.5"
use framework "Foundation"
use scripting additions

property || : a reference to current application

set now to (current date)
set currentCalendar to ||'s NSCalendar's currentCalendar()
set threeMonthsFromNow to (currentCalendar's dateByAddingUnit:(||'s NSCalendarUnitMonth) value:3 toDate:now options:(||'s NSCalendarMatchNextTime)) as date

I’m not certain how “selected date” is specified but the following is a handler written by Nigel. It’s very fast, taking less than a millisecond to run:

set oldDate to date "2/1/2022" -- use date format in locale
set newDate to addMonths onto oldDate by 3 --> date "Sunday, May 1, 2022 at 12:00:00 AM"
-- set {year:y, month:m, day:d} to newDate -- if needed elsewhere in script

on addMonths onto oldDate by m
	copy oldDate to newDate
	set {y, m} to {m div 12, m mod 12}
	if m < 0 then set {y, m} to {y - 1, m + 12}
	set newDate's year to (newDate's year) + y
	if m is not 0 then tell newDate to set {day, day} to {32 * m, day}
	if newDate's day is not oldDate's day then set newDate to newDate - (newDate's day) * days
	return newDate
end addMonths

https://macscripter.net/viewtopic.php?id=24737

Hi Stefan Many thanks for your rapid reply, how do I substitute set now to (current date) for set now to a date variable. My script reads a .csv file which contains a issue date (format dd/mm/yyyy) which I need to generate a due date.

It depends on the locale of your computer, but in many cases the dd/mm/yyyy format works

set dateString to "17/01/2022"
set theDate to date dateString

Thanks Stefan and peavine, just what I needed, an embarrassment of solutions!!

Well, upon further testing, it turns out Nigel’s script does not work reliably. It was written almost 15 years ago and relies on the result explained below, so perhaps this should not surprise. Fortunately, Stefan’s suggestion works great.

There’s a ‘newer’ version here. Please test that. It works fine here (macOS 10.11).

Hi peavine.

Could you give me an example where it doesn’t work? I’m not challenging your findings, just trying to understand the problem. :slight_smile:

Nigel. I’ve included an example below, which uses 4 months, but it also seems not to work with 5 to 11 months.

on addMonths onto oldDate by m -- returns a date
	copy oldDate to newDate
	-- Convert the month-offset parameter to years and months
	set {y, m} to {m div 12, m mod 12}
	-- If the month offset is negative (-1 to -11), make it positive from a year previously
	if m < 0 then set {y, m} to {y - 1, m + 12}
	-- Add the year offset into the new date's year
	set newDate's year to (newDate's year) + y
	-- Add the odd months (at 32 days per month) and set the day
	if m is not 0 then tell newDate to set {day, day} to {32 * m, day}
	-- If the day's now wrong, it doesn't exist in the target month
	-- Subtract the overflow into the following month to return to the last day of the target month
	if newDate's day is not oldDate's day then set newDate to newDate - (newDate's day) * days
	return newDate
end addMonths

addMonths onto (current date) by 4
--> date "Wednesday, August 18, 2021 at 5:58:39 AM"

Thanks, peavine. Gosh. Yes. Something’s changed under the bonnet since that was written. So far though, the “newer” version to which alastor933 linked above seems to be OK.

Nigel. I tested the newer version and it works great. When responding to your post earlier this morning, I inadvertently missed alastor933’s post–sorry about that. So, we’re back to two good scripts that will do the job. :slight_smile: