Time to GMT for dates not in present daylight savings/standard time

What I’d like to do is convert an arbitrary timestamp to UTC. For dates in the current daylight savings/standard time season, the following works well (as established here):

set _utcTimestamp to _localTimestamp - (time to GMT)

However, the time difference to GMT differs depending on the current date. In my case, daylight savings time is four hours behind GMT. During standard time, the difference is five hours. This is good for obtaining the current time in GMT, but it results in GMT timestamps that are an hour off if the _localTimestamp date does not fall in the present daylight savings/standard time period.

Is there a way to make “time to GMT” report the time difference for a given date? Something effectively like “time to GMT for _date” that returns -4 hours if _date falls in daylight savings time but -5 hours if _date falls in standard time? I’m hoping there is a reliable AppleScript idiom or command line tool that can be used for this purpose without resorting to hard-coded kludges, especially what with the recent changes to daylight savings policy here in the US.

Any ideas or suggestions would be appreciated. Thanks,
Jim

See this thread in Code Exchange: http://bbs.applescript.net/viewtopic.php?id=20773

I’ve pared that example down to a handler that returns a GMT date equivalent to the local date it is given. In my case, if the date given to ConvertToGMT falls in standard time, it returns a time 5 hours ahead. If the date given is in daylight savings time, ConvertToGMT returns a time 4 hours ahead. Here is the code (I notice the shell script’s quote escaping sort of confuses the forum’s syntax highlighter):

on parseDumpedDate(dateString)
	set a to date (text (word 4) thru (word -3) of dateString)
	set day of a to word 3 of dateString
	set month of a to ((offset of (word 2 of dateString) in "JanFebMarAprMayJunJulAugSepOctNovDec") + 2) div 3
	set year of a to word -2 of dateString
	return a
end parseDumpedDate


on ConvertToGMT(_inputDate)
	
	try
		-- Get a list of significant DST dates in _localDate's year.
		set _dstData to run script ("{" & text 1 thru -3 of ¬
			(do shell script "/usr/sbin/zdump -v /etc/localtime | sed -E -e '/" & year of _inputDate & "/!d' -e 's|^[^ ]+ *|{_utcDate:\"|g' -e 's/ = /\", _localDate:\"/' -e 's/ isdst=1/\", _isDST:true},¬/' -e 's/ isdst=0/\", _isDST:false},¬/'") ¬
				& "}")
	on error
		-- Use plain GMT offset if no local DST data is available.
		return _inputDate - (time to GMT)
	end try
	
	-- Initialize defaults.
	set _dstOffset to time to GMT
	set _stdOffset to time to GMT
	set _dstLocal to (current date)
	set _stdLocal to _dstLocal
	
	-- Inspect each DST data point.
	set _prevData to null
	repeat with _data in _dstData
		
		-- Any transition between DST and standard time is of interest.
		if (_prevData is not null and _prevData's _isDST is not _data's _isDST) then
			
			-- Convert the last data point's dates into AppleScript date objects.
			set _dataLocal to parseDumpedDate(_prevData's _localDate)
			set _dataUTC to parseDumpedDate(_prevData's _utcDate)
			
			-- Record the seasonal offset to GMT and the season endpoints.
			if (_data's _isDST) then
				-- We have entered DST; the dates are the last standard times.
				set _stdOffset to (_dataLocal - _dataUTC)
				set _dstLocal to _dataLocal
			else
				-- We have entered standard time; the dates are the last DST times.
				set _dstOffset to (_dataLocal - _dataUTC)
				set _stdLocal to _dataLocal
			end if
			
		end if
		
		set _prevData to _data
		
	end repeat
	
	-- Determine which GMT offset to use based on the sequence of _inputDate and the DST dates.
	if _dstLocal is less than _stdLocal then
		-- DST in middle of year (northern hemisphere)
		if (_inputDate is less than or equal to _dstLocal) or (_inputDate is greater than _stdLocal) then
			return _inputDate - _stdOffset
		else
			return _inputDate - _dstOffset
		end if
	else if _stdLocal is less than _dstLocal then
		-- Standard time in middle of year (southern hemisphere)
		if (_inputDate is less than or equal to _stdLocal) or (_inputDate is greater than _dstLocal) then
			return _inputDate - _dstOffset
		else
			return _inputDate - _stdOffset
		end if
	end if
	
	-- default return only if _dstLocal equals _stdLocal (only if no or incomplete _dstData)
	return _inputDate - (time to GMT)
	
end ConvertToGMT

ConvertToGMT(date "Wednesday, January 10, 2007 12:00:00 AM")
--ConvertToGMT(date "Friday, June 1, 2007 12:00:00 AM")
--ConvertToGMT(date "Wednesday, December 12, 2007 12:00:00 AM")
--ConvertToGMT(date "Sunday, November 4, 2007 1:59:59 AM") -- 5:59:59 AM
--ConvertToGMT(date "Sunday, November 4, 2007 2:00:00 AM") -- 7:00:00 AM

I have not tested it extensively, nor have I tested it at all for other time zones. Please share any corrections, particularly if you find a time zone it doesn’t handle correctly. That it works in my case is sufficient for me, but I would prefer to know that it works consistently around the world. Thanks for your help.

Jim

Just to follow up, I used this in my “Backdate Yojimbo Items” script: http://anoved.net/2007/05/backdate-yojimbo-items.html

Hi, Anoved;

In my case, Atlantic Standard Time/Daylight Time (4/3 hours behind GMT) it works for all the dates you gave. After a few more responses (perhaps a European) why not post it to the end of the thread in Code Exchange?

Hi,

the ConvertToGMT routine works fine here in Switzerland.
Here some lines which are independent from international date format settings

tell (current date) to set theDate to it - (its time)
tell theDate to set {its day, its month, its year} to {23, 3, 2007} -- daylight savings time changes at march 25th
repeat with i from 1 to 4
	display dialog (ConvertToGMT(theDate + i * days) as string)
end repeat