Converting AppleScript Dates to UTC

8 Jan 2012 - 15:09

This is a simple handler to convert an AppleScript date to Universal Time Co-ordinated (aka Greenwich Mean Time).

Zur deutschen Version)

(The inverse handler is under UTC Date to Local Date/Time AppleScript

AppleScript has a command time to GMT, which gives the difference of the local time to UTC at the current moment in seconds. Hence (current date) - (time to GMT) returns the current time in UTC.

But this fails for arbitrary dates. If you are in the part of the year which uses standard time but try to convert a date on a day in summer time / daylight saving time, the result is wrong.

The following handler uses the conversion to property lists provided by System Events. This converts any date to UTC taking the Olson time zone of your Mac into account. Such a time zone knows the rules for time changes since 1970. So even a date decades ago should be converted correctly.

Since calling a program like System Events takes some time, the handler allows for converting a list of dates in one call. The result will be a date, if the argument is a date, it will be a list of dates, if the argument is a list of dates.

on date_to_utc(list_arg)
	-- change the value of a date or a list of dates to
	-- the Universal Time Coordinated time zone
	-- Argument can be a date or a list of dates
	-- Result for a date is a date,
	-- result for a list is a list
	
	-- make sure, argument is list. Store original state
	set type_is_list to true
	if class of list_arg is not list then
		set list_arg to {list_arg}
		set type_is_list to false
	end if
	
	-- serialize arguments to plist using system events
	tell application "System Events"
		set plist to (make new property list item with properties {value:list_arg})
		set strg to text of plist
	end tell
	-- create some arbitrary date for manipulation
	copy item 1 of list_arg to date_obj
	
	-- raise error if first element of list is not convertable to date
	try
		set date_obj to date_obj as date
	on error the_error number errnum
		error the_error & " In handler date_to_utc." number errnum
	end try
	set {time of date_obj, day of date_obj, month of date_obj} to {0, 1, 1}
	
	-- find date entries in plist
	set old_delims to AppleScript's text item delimiters
	set AppleScript's text item delimiters to {"", ""}
	set temp_list to every text item of strg
	set r_list to text items 2 thru -2 of strg
	set datestrings to {}
	repeat with c from 2 to count temp_list by 2
		copy item c of temp_list to end of datestrings
	end repeat
	-- Here, we have a list of strings, representing
	-- dates in ISO notation for Zulu time zone
	-- converting the strings
	set r to {}
	set AppleScript's text item delimiters to {"-", "T", ":", "Z"}
	repeat with J from 1 to (count datestrings)
		set curr to item J of datestrings
		log "curr: " & curr
		set tl to every text item of curr
		-- result has 7 elements, the last one is empty
		log tl
		set curr to items 1 thru 6 of curr
		-- here we have a list of year, month, day, hour, minute and second as strings
		copy date_obj to ld
		-- next will set date_ob and implicitelly change strings to integers
		set {year of ld, month of ld, day of ld, hours of ld, minutes of ld, seconds of ld} to tl
		copy ld to end of r
	end repeat
	if (count r) ? (count list_arg) then
		-- this should occur only if some of the entries in the plist were
		-- of other types
		error "Some values are no dates in handler date_to_utc." number 1700
	end if
	
	-- if original argument was single, make return value single agein
	if not type_is_list then
		set r to item 1 of r
	end if
	set AppleScript's text item delimiters to old_delims
	return r
end date_to_utc

Example: On my machine, running with German format settings and in the time zone Europe/Berlin,

date_to_utc({current date, date ("15.5.2010 12:00:00"), date ("15.5.1975 12:00:00")})

returns

{date "Sonntag, 8. Januar 2012 14:55:54", date "Samstag, 15. Mai 2010 10:00:00", date "Donnerstag, 15. Mai 1975 11:00:00"}

Note that in Mai 2012 and in May 1975, the conversion is different. We did not use summer time in the seventies.