I believed it to be that simple. Well, here is a correction. I don’t tamper with the system date, but I guess this should work.
Thank you for your correction Stefan
@Val the “rollover” trick only works forwardly for months, within a certain range, I wonder if it was 18 or 19 months or so.
tell (current date)
if its month is not January then
set its month to (its month as integer) - 1
else
set its month to December
set its year to (its year as integer) - 1
end if
return it --> One calendar month before this instant.
end tell
I fiddled with your last example, and by doing that I figured out how the date functions.
Every property is a separate of seconds or can be viewed as seconds.
Every larger property contains the next lower property.
The year contains the seconds of the month: every brand new second is added to every property of the date object (the year contains the date value in seconds effectively).
They are however separate entities, -they share no common seconds.
Thats why a month will be the next month when adding a non existent number of days, and previous when telling it that it contains nil days. And if it were the first month, it will rollover and become the last month, when operating with seconds.
And your brilliant example worked and will always work because you subtract from the year first. Very clever indeed.
I think (maybe) this works a la McUsr’s code at post 21.
But Is this jumping unnecessary hoops when it probably can be done in one elegant line ?
set Priormonthsa to text returned of (display dialog "How many months prior to this date do want to investigate ? - Please Insert Number" with title "How far back do you want to go?" default answer 12) as number
if Priormonthsa > 12 then
set n to Priormonthsa div 12
set m to n
set Priormonths to Priormonthsa mod 12
else
set Priormonths to Priormonthsa
set m to 0
set n to 1
end if
tell (current date)
if Priormonths is not greater than ((its month as integer) - 1) then
set its month to (its month as integer) - Priormonths
set its year to (its year as integer) - m
else
set its month to (its month as integer) + (12 - Priormonths)
set its year to (its year as integer) - (Priormonthsa / 12 as integer)
end if
return it
end tell
I was told many years ago that a date (in AppleScript) was related to a record. In fact another term for “date object” is “date record”. However, I also understand a date to be a very large integer representing seconds from 1st January 1904 00:00:00, with negative numbers representing dates and times before that. I imagine that the various “properties” are actually functions which perform the necessary maths to extract the relevent figures or to fold them into the integer value.
A more self-explanatory rendition of this would be:
set aDate to (current date)
set lastDayOfPreviousMonth to aDate - (aDate's day) * days
set aDate's year to lastDayOfPreviousMonth's year
set aDate's month to lastDayOfPreviousMonth's month
return aDate
The idea was to modify and return the ‘current date’ date object, but of course you could just as easily return another:
tell (current date) to return it - ((it - (its day) * days)'s day) * days
set n to text returned of (display dialog "How many months prior to this date do want to investigate ? - Please Insert Number" with title "How far back do you want to go?" default answer 12) as number
set aDate to (current date)
repeat n times
set lastDayOfPreviousMonth to aDate - (aDate's day) * days
set aDate's year to lastDayOfPreviousMonth's year
set aDate's month to lastDayOfPreviousMonth's month
end repeat
return aDate
set n to text returned of (display dialog "How many months prior to this date do want to investigate ? - Please Insert Number" with title "How far back do you want to go?" default answer 12) as number
tell (current date) to return it - (((it - (its day) * days)'s day) * days) * (n+1)
Sorry to keep you waiting, Val. I’ve long had a handler for adding or subtracting calendar months, but it’s broken in Snow Leopard. Here’s a fixed version which should work on any system (so far!).
on addMonths onto oldDate by m
copy oldDate to newDate
-- Convert the "months" 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} -- Broken in SL.
-- Fix:
repeat m times
set newDate's day to 32
end repeat
set newDate's day to oldDate's day
-- End of fix.
-- 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 instead.
if (newDate's day is not oldDate's day) then set newDate to newDate - (newDate's day) * days
return newDate
end addMonths
-- Add 40 years (480 calendar months)
addMonths onto (current date) by 480
-- Subtract 18 months
addMonths onto (current date) by -18
My original addMonths handler used day overflow because it was written before it was possible to set months by number. Here’s a more modern version. I don’t know if it works in Panther or not. Certainy not before.
on addMonths onto oldDate by m
copy oldDate to newDate
set d to oldDate's day
-- Get the new month number relative to this year.
set m to (oldDate's month) + m
-- Derive the actual year and month number.
set {y, m} to {(oldDate's year) + m div 12, m mod 12}
-- If the month number is less than 1, get the complementary positive number in the previous year.
if (m < 1) then set {y, m} to {y - 1, m + 12}
-- Set the required values in the new date.
tell newDate to set {its day, its year, its month, its day} to {1, y, m, d}
-- 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 instead.
if (newDate's day is not d) then set newDate to newDate - (newDate's day) * days
return newDate
end addMonths
-- Add 40 years (480 calendar months)
addMonths onto (current date) by 480
-- Subtract 18 months
addMonths onto (current date) by -18