Calculating the UTC offset in your SAS session

Update 25Nov2010: I've updated this example to correct the code so that it works correctly for positive UTC offsets. Thanks to Bruno Müller, my colleague at SAS, for finding my mistakes.

One of my SAS colleagues was recently working on a project where she had to create reports that include the UTC offset encoded into the report. The UTC offset is that part of your computer time zone notation that indicates how far off the local time is from "Coordinated Universal Time" (which, in practice, is the same as Greenwich Mean Time). For example, I live on the east coast of USA, which puts me in UTC -05:00. My colleagues in Sydney, Australia are in UTC +11:00 at the moment (since they are enjoying their daylight savings time).

Prior to SAS 9.2, gathering this information required that you use some type of shell command to get the UTC offset value from your host machine (using systeminfo on Windows or date -u on Unix). But with SAS 9.2, you can use the new E8601LZ format to help calculate the correct value in a platform-independent way. (This SAS format is part of a group of formats and informats that support ISO 8601 date and time notations.)

There is also an undocumented function, gmtoff(), which returns the raw number for the offset in seconds. Even though the function is not documented, it does appear in some examples on support.sas.com--so I don't feel that I'm revealing too many secrets by sharing it with you.

Update: SAS 9.4 now has an official version of this function, named TZONEOFF(). GMTOFF() still works for now as well, still undocumented. Adjust your future SAS programs accordingly.

Here is a SAS program example that calculates the UTC offset for the machine that hosts your SAS session:

data _null_;
length
utc_offset_display $ 7
utc_offset 8;
/* E8601LZ formats as a UTC value and converts to a local time */
utc_offset_display=substr( put('00:00:00't,E8601LZ.), 9);
utc_offset=gmtoff()/3600; /* undocumented */
call symput('utc_offset',utc_offset);
call symput('utc_offset_display',utc_offset_display);
run;

%put &utc_offset_display;
%put &utc_offset;

When I run this on my machines in Cary, NC, the output log looks like this:

27         %put &utc_offset_display;
-05:00
28         %put &utc_offset;
-5

Special thanks to one of my colleagues in SAS Japan, Shin Kayano, who is one of our software globalization experts. He's the one who pointed me to this method of using the E8601LZ format.

Update: you can achieve the same result in SAS 9.1.3, but the format name was IS8601LZ instead of E8601LZ. In SAS 9.1.3, these formats were added mainly in support of the XML LIBNAME engine.