Two questions regarding date handling

Hello.

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

tell (current date)
	set {year:year, month:its month} to it - (its day) * days
	return it
end tell

. with the same proviso about non-existent days.

Wow! :lol:

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.

And thanks for the insights.

I love these threads. :lol: Nigel was on a roll…

How would this be done with Nigel’s code ?

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

Val

Hi, McUsr.

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

Maybe this ?

One line is a step way too far for me !

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

Many thanks.

Val

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)

Nearly but Not quite there.

Val

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

A gem!

Many thanks,

Val

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

Hello

I’m positively sure that months as number was a feature added in Tiger