To clarify what I understand the situation to be:
AppleScript date objects are a hang-over from simpler days. They operate a strictly proleptic Gregorian calendar with no regard for time zone, daylight savings, leap seconds, or other adjustments. But within these limits, they’re mathematically very reliable:
set fourHundredYears to (365 * 400 + 97) * days
set twoThousandYears to fourHundredYears * 5
set now to (current date)
set twoThousandYearsAgo to now - twoThousandYears
return {year, month, day, hours, minutes, seconds} of now & linefeed & {year, month, day, hours, minutes, seconds} of twoThousandYearsAgo
The only things to remember with very early dates is that the ‘year’ of 1 BC is 0, that of 2 BC is -1, etc. and that negative years can’t be set directly.
Applications and macOS itself use another date system which does take into account time zones and daylight savings regimes. It’s believed that AppleScript dates will eventually be changed to use this, but it would undoubtedly break many existing scripts.
There’s also a formatting system which converts dates expressed as strings into AppleScript dates and vice versa using the date and time format preferences set on the user’s own computer. (System Preferences → Language & Region → Advanced… → ‘Dates’ and ‘Times’.) It’s this which seems not to be delivering the goods properly with dates some distance removed from the present. Previous discussions with Shane and Yvan about this have revealed that the degree of error and the cut-in dates for it occurring depend on whereabouts in the world you are. This suggests that time zone plays a part in the error, although I suspect that the date and time formats being converted may also have an effect. I haven’t looked into it that deeply.
Bringing the string formatter into play in the script above:
set fourHundredYears to (365 * 400 + 97) * days
set twoThousandYears to fourHundredYears * 5
set now to (current date)
set twoThousandYearsAgo to now - twoThousandYears
return {year, month, day, hours, minutes, seconds, date string, time string} of now & linefeed & {year, month, day, hours, minutes, seconds, date string, time string} of twoThousandYearsAgo
The (date eachDate) in Mr. Science’s first script should produce an AppleScript date whose date is the one suggested by the string and whose time is 0 (since the time isn’t specified in the string). But when the year in the string is 1883 or earlier, the AppleScript date actually produced on his machine is a few seconds before that — ie. some during the previous day: December 31 1882.
The reason Mr. Science is getting the wrong month for February with his second script (post #6) is that he’s missed my earlier point about setting the day to 1 before setting anything else. Running the script today (30th December 2017) gets a current date whose year, month, and day are respectively 2017, December, and 30. Setting the year first to 1883 simply changes the date to represent December 30 1883. But then setting the month to 2 (or February) changes the date to February 30 1883. Since there were only 28 days in February that year, the date overflows and becomes March 2 1883. Setting the day to 2 after that simply keeps the date as March 2. When using current date as a basis for building dates, you should set the day to 1 first (or to any day which exists in every month) so that such overflows can’t occur.
set y to 1883
set someDates to {{y, 1, 1}, {y, 2, 2}, {y, 3, 3}, {y, 4, 4}, {y, 5, 5}, {y, 6, 6}, {y, 7, 7}, {y, 8, 8}, {y, 9, 9}, {y, 10, 10}, {y, 11, 11}, {y, 12, 12}}
set rprt to return
repeat with eachDate in someDates
set {yr, mo, dy} to eachDate
tell (current date) to set {earlyDate, its day, its year, its month, its day, its time} to {it, 1, yr, mo, dy, 0}
set rprt to rprt & "The month number of " & date string of earlyDate & " is " & mo & return
end repeat
return rprt