How to create a Calendar event on a specific day of next month?

Hello all,

I am trying to create a Calendar event on a specific day of next month (the
18th, in this case).

I am using this workaround, as I generally create the event a month in advance:

set theStartDate to (current date) + (30 * days)

But due to months having different quantities of days (or due to the day that I
execute the script on), the event may be created on the wrong day.

Here is the draft of the entire script:

set theStartDate to (current date) + (30 * days)
set hours of theStartDate to 14
set minutes of theStartDate to 0
set seconds of theStartDate to 0
set theEndDate to theStartDate + (3 * hours)
tell application "Calendar"
        tell calendar "Home"
                set newEvent to make new event at end with properties
{summary:”Rent is due", location:"Venmo", allday event:true, start
date:theStartDate, end date:theEndDate, description:"This is your courtesy
reminder to pay your rent.", url:"https://venmo.com/account/sign-in"}
                tell newEvent
                        make new sound alarm at end of sound alarms with
properties {trigger interval:840, sound name:"Crystal"}
                        make new sound alarm at end of sound alarms with
properties {trigger interval:-120, sound name:"Crystal"}
                        make new sound alarm at end of sound alarms with
properties {trigger interval:-10200, sound name:"Crystal"}
                end tell
        end tell
end tell

Thanks for any help!

Sincerely,

Jim

Hi Jim.

I just replied to your ASUL post, but thought I’d also reply here where it is a better repository of scripts.

Manipulating dates in AppleScript is one of the most frustrating tasks there is, especially if you are familiar with other languages that have rich date functions built in.

IAC, I hope you’ll find this helpful.

First, here’s a great date resource:
Dates & Times in AppleScripts – MacScripter Adam Bell et al

I actually reviewed that again, but did not find a concise solution to your problem, but I may have missed it since there is so much there. I’m sure that @NigelGarvey will jump in if it missed it, or there is a better method.

So, here is what I came up with, based in part on the MacScripter’s scripts

property ptyScriptName : "Get Next Month Same Day"
property ptyScriptVer : "1.0"
property ptyScriptDate : "2021-06-19"
property ptyScriptAuthor : "JMichaelTX"

(*
    REF: Dates & Times in AppleScripts -- MacScripter/Adam Bell et al
            https://macscripter.net/viewtopic.php?id=24737)
            2007-07-23
*)

set startDate to (current date)
set {month:m, day:d, year:y} to startDate

copy startDate to nextMonth

--- Set to Next Month After StartDate ---
set nextMonth's day to 32

--- Set to the Month After Next Month --
set nextMonth's day to 32
set manmDay to day of nextMonth

--- Now Set Back to Last Day of Next Month ---
set nextMonth to nextMonth - (manmDay * days)
set lastDay to day of nextMonth

--- Finally Set the Day of Next Month, but no later than it's last day ---
if (d ≤ lastDay) then
  set nextMonth's day to d
end if

return nextMonth

-->date "Monday, July 19, 2021 at 6:15:30 PM"
1 Like

Hey Jim,

So you’re trying to get the 18th of the month for next month?

tell (current date)
   set its month to (its month) + 1
   set its day to 18
   set its hours to 14
   set its minutes to 0
   set its seconds to 0
   set newDate to it
end tell

newDate

-Chris

1 Like

@JMichaelTX — Wow. that link to date resources is amazing! Thank you!

I don’t think I explained the goal well—I always want the new date to the the 18th of the next month, regardless of the date the script is executed on.

@ccstone — you nailed it.

Thank you to both of you!

Here is my completed script, in case it is of help to anyone else:

tell (current date)
	set its month to (its month) + 1
	set its day to 18
	set its hours to 14
	set its minutes to 0
	set its seconds to 0
	set theStartDate to it
	set theEndDate to theStartDate + (3 * hours)
	tell application "Calendar"
		tell calendar "Home"
			set newEvent to make new event at end with properties {summary:"Rent is due", location:"Venmo", allday event:true, start date:theStartDate, end date:theEndDate, description:"This is your courtesy reminder to pay your rent.", url:"https://venmo.com/account/sign-in"}
			tell newEvent
				make new sound alarm at end of sound alarms with properties {trigger interval:840, sound name:"Crystal"}
				make new sound alarm at end of sound alarms with properties {trigger interval:-120, sound name:"Crystal"}
				make new sound alarm at end of sound alarms with properties {trigger interval:-10200, sound name:"Crystal"}
			end tell
		end tell
	end tell
end tell
1 Like

That’s great Chris.

Maybe I missed it but I did not see that in the MacScripter section on dates.

They go through all kinds of machinations to get to the next and prior months.

1 Like

Hi.

When setting a current date result to a new date, it’s a good idea to set the day to something below 29 first. This is to prevent overflow (or maybe carry) if any of the changes aren’t compatible with the date’s value at the moment of setting. For instance, if Chris’s code’s run on 31st of May, setting the current date result’s month to June will give 31st June. And since June only has 30 days, the additional day will roll over onto 1st July. So the final result will be 18th July instead of 18th June.

Since the day wanted here is 18, which occurs in every month, a simple expedient would be to set the day before setting month:

tell (current date)
	set its day to 18
	set its month to (its month) + 1
	set its hours to 14
	set its minutes to 0
	set its seconds to 0
	set newDate to it
end tell

But in general, when changing a date object’s properties, it’s best to set the day to a low figure first and then what ever other details need to be changed:

tell (current date)
	set its day to 1
	set its month to (its month) + 1
	set its day to 18
	set its hours to 14
	set its minutes to 0
	set its seconds to 0
	set newDate to it
end tell

Addendum:

I’ve just remembered another alternative that would do the trick here …

(Later.) Sorry. This is actually similar to what @JMichaelTX suggested above. I should have read his script more closely. :frowning:

tell (current date)
	set its day to 32
	set its day to 18
	set its time to 14 * hours
	set newDate to it
end tell
2 Likes

Thank you @NigelGarvey !