Dealing with ISO 8601 dates

This topic came up elsewhere, but some people here might have missed it. The issue is making dates from ISO 8601 strings, which can come in a variety of forms. In particular, dealing with time zones is tricky in AppleScript.

But there’s a third-party open-source framework that fits the bill nicely. You can read about it and download it here: https://github.com/boredzo/iso-8601-date-formatter. It handles most formats, including week date and ordinal date formats. That download is not going to be much use to most scripters, but essentially it can compile into a framework that can be called from AppleScript. I’ve compiled the framework, and you can download it here: https://www.macosxautomation.com/applescript/apps/ISO8601_framework.zip.

Once you add it to your system, either in ~/Library/Frameworks or within a library or other script bundle, calling it is simple. You can make it run in a strict mode, or the default of more lenient parsing, where it handles different delimiters and things like leading spaces. Here’s an example script:

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use framework "ISO8601"
use scripting additions

my ISO8601DateFrom:"2016-01-05 13:01:15"
my ISO8601DateFrom:"2016-01-05"
my ISO8601DateFrom:"2016-01-05T13:01:15"
my ISO8601DateFrom:"2016-01-05 13:01"
my ISO8601DateFrom:"2016-01-05T13:01:15Z"
my ISO8601DateFrom:"2016-01-05 13:01:15+1100"
my ISO8601DateFrom:"2007-W01-01"
my ISO8601DateFrom:"2007-W01-01T13:24:56-0800"
my ISO8601DateFrom:"-01-05"
my ISO8601DateFrom:"2017-032"

on ISO8601DateFrom:theString
	set theFormatter to current application's ISO8601DateFormatter's new()
	set theDate to theFormatter's dateFromString:theString
	considering numeric strings
		if AppleScript's version < "2.5" then
			set theDate to my makeASDateFrom:theDate
		else
			set theDate to theDate as date
		end if
	end considering
	return theDate -- AppleScript Date
end ISO8601DateFrom:

-- Required before 10.11
on makeASDateFrom:theNSDate
	set theCalendar to current application's NSCalendar's currentCalendar()
	set comps to theCalendar's componentsInTimeZone:(missing value) fromDate:theNSDate -- 'missing value' means current time zone
	tell (current date) to set {theASDate, year, day, its month, day, time} to ¬
		{it, comps's |year|(), 1, comps's |month|(), comps's |day|(), (comps's hour()) * hours + (comps's minute()) * minutes + (comps's |second|())}
	return theASDate
end makeASDateFrom:

There are also methods for setting the time zone, as well as making strings from dates.

1 Like