This looks like an attempt to handle BC dates, but in fact it turns them into AD ones. Not that that’s very likely to reduce its usefulness.
Here is an attempt to produce the same results as the scripting bridge with both AD and BC dates. I haven’t tried it with every possible date in every known time zone, but it’s looking hopeful so far ….
use AppleScript version "2.3.1" -- Mavericks (10.9.something) or later
use framework "Foundation"
use scripting additions
set ASDate to (current date) - 1000000 * days --> A date in January 721 BC on the day of posting.
set newNSDate to makeNSDateFrom(ASDate)
set newASDate to makeASDateFrom(newNSDate)
return {ASDate, newNSDate, newASDate}
on makeNSDateFrom(theASDate)
-- If the date's before about 1800, its time string's likely to be out with its time. To match the result from a scripting bridge conversion, we need an AS date with properties matching the string from the original.
-- Get the same date in a known recent year.
copy theASDate to recentDate
set recentDate's year to 2000
-- Derive dates in the current year from the original and recent dates' time strings and get the diffence between them.
set timeAdjustment to (date (theASDate's time string)) - (date (recentDate's time string))
-- Subtract a day from the result if it's > 0.
if (timeAdjustment > 0) then set timeAdjustment to timeAdjustment - days
-- Add this figure to the original date to get one with the required properties.
set theASDate to theASDate + timeAdjustment
-- Get the properties!
set {y, m, d, t} to theASDate's {year, month, day, time}
-- Positive year numbers, including 0 (1BC), are in era 1; negative in era 0.
set theEra to (y > -1) as integer
-- If the year number's negative, get the positive BC equivalent instead.
if (theEra is 0) then set y to 1 - y
-- Create and return the corresponding NSDate.
set theCalendar to current application's NSCalendar's currentCalendar()
return theCalendar's dateWithEra:(theEra) |year|:(y) |month|:(m as integer) |day|:(d) hour:(0) minute:(0) |second|:(t) nanosecond:(0)
end makeNSDateFrom
on makeASDateFrom(theNSDate)
-- Get the relevant components from the NSDate.
set theCalendar to current application's NSCalendar's currentCalendar()
set comps to theCalendar's componentsInTimeZone:(missing value) fromDate:theNSDate
tell comps to set {theEra, y, m, d, h, min, s} to {its era(), its |year|(), its |month|(), its |day|(), its hour(), its minute(), its |second|()}
if (theEra is 1) then
-- AD dates and those in 1BC are straightforward.
tell (current date) to set {theASDate, its day, its year, its month, its day, its hours, its minutes, its seconds} to {it, 1, y, m, d, h, min, s}
else
-- 2BC and earlier will need negative years, which can't be set directly in AS dates.
-- Get an AS date representing the first instant of 1AD. (Its date string may be several seconds out.)
tell (current date) to set {eraStartDate, its day, its year, its month, its time} to {it, 1, 1, 1, 0}
-- Get an AS date roughly halfway through the AD year with the same number as the BC year number from the components,
copy eraStartDate to ADDate
tell ADDate to set {its year, its month} to {y, July}
-- Subtract to get a date somewhere in the middle of the BC year.
set theASDate to eraStartDate - (ADDate - eraStartDate)
-- Set the other properties of that year to those from the components.
tell theASDate to set {its day, its month, its day, its hours, its minutes, its seconds} to {1, m, d, h, min, s}
end if
-- If necessary, perform the reverse of the time adjustment in the handler above.
copy theASDate to recentDate
set recentDate's year to 2000
set timeAdjustment to ((date (theASDate's time string)) - (date (recentDate's time string)))
if (timeAdjustment > 0) then set timeAdjustment to timeAdjustment - days
set theASDate to theASDate - timeAdjustment
return theASDate
end makeASDateFrom
For side-by-side testing, here’s the same thing using the scripting bridge:
use AppleScript version "2.5" -- El Captitan (10.11) or later
use framework "Foundation"
use scripting additions
set ASDate to (current date) - 1000000 * days
set newNSDate to (current application's NSDate's dateWithTimeInterval:(0) sinceDate:(ASDate))
set newASDate to newNSDate as date
return {ASDate, newNSDate, newASDate}