Computing server time zone difference in classic ASP ... take 2

Antic from Jodohost pointed me to an even more elegant solution: use mixed JavaScript/VBScript to get the result. JavaScript can compute the timezone difference with a built-in function and VBScript can then use the results.

Here is the minimum code to get the desired result:
<script runat="server" language="jscript">
var TZDiff = new Date().getTimezoneOffset();

</script>
<% Response.Write TZDiff %>

Of course, if you care about ASP performance, you might not want to invoke two script interpreter engines in a single page. In that case, a more optimized solution is:

GetTZ.asp:
<%@ LANGUAGE=JScript %>
<% Application("TZOffset") = new Date().getTimezoneOffset() %>

Any other ASP page:
<%
If Not IsNumeric(Application("TZOffset")) Then Server.Execute("GetTZ.asp")
' use Application("TZOffset") from here on
%>

Computing Timezone difference from GMT in ASP VBScript

If you want to be nice to your web visitors, you will eventually have to start considering the "last-modified" HTTP headers in order to make sure that:
  • the browsers always get the most accurate data and
  • the dial-up users don't wait for data they have already cached.

Before getting there, you'll hit a major obstacle - all HTTP timestamps are in GMT (and in an obscure format, on top of that) and the time you get with the now() function is local to your timezone. No big deal in most languages - you just use system calls or DLLs to figure out the difference between local time and GMT ... but you can't do that in ASP. Writing a custom COM module is always an option if you own the web server (in which case you can hardcode the timezone offset anyway), but for those of us who rely on hosting (and distributing code), things get almost impossibly complex.

But, as always, there is a trick - using the XMLHTTPRequest object, the ASP script can execute a request on its own server (http://127.0.0.1) and compare the GMT timestamp in the reply with the current time to get the local timezone difference.

Here is the code to do it:

'
' FromHTTPDate - helper function that converts HTTP date
' into a date value
'
Function FromHTTPDate (SDate)
Dim n,LC,S
n=InStr(1,SDate,";",vbTextCompare)
If (n>0) Then
S = Left(SDate,n-5)
Else
If SDate > "9" Then S = Left(SDate,Len(SDate) - 4)
End If
n=InStr(1,S," ",vbTextCompare)
If (n>0) Then S = Mid(S,n+1,Len(S))
LC = Response.LCID : Response.LCID = 1033
FromHTTPDate=CDate(S) : Response.LCID = LC
End Function

'
' GetTimezoneDifference - returns hourly difference between
' local time and GMT
'
Function GetTimezoneDifference
Dim TZD
TZD = Application ("TimezoneDifference") ' reuse the result
If TypeName(TZD) = "Integer" Then ' if available
GetTimezoneDifference = TZD : Exit Function
End If

Dim HttpReq,Port,URL,RDT

Set HttpReq = Server.CreateObject("MSXML2.ServerXMLHTTP")
Port = Request.ServerVariables("SERVER_PORT")
URL = "http://127.0.0.1" & ":" & Port & "/"
HttpReq.open "GET", URL , False
HttpReq.send

RDT = FromHTTPDate(HttpReq.getResponseHeader("Date"))
TZD = CInt((Now() - RDT) * 24 + 0.05)
Application ("TimezoneDifference") = TZD ' cache the result
GetTimezoneDifference = TZD
End Function

Handling Variant byte array in ASP

This is yet another of slightly undocumented ASP features - you can find a lot of examples telling you how to read and write binary data (with, among other things, Response.binaryWrite or ADODB_recordset("blob").value), but when you try to manipulate individual bytes (I had to compute MD5 hash), uncle Google or Microsoft search gives you nothing.

The trick is (as always) very simple: you treat variant byte array as string, using regular string functions (like Len, Mid or Asc). However, due to Unicode support in VBScript, you have to use their byte versions. So, to dump the variant byte array, use this code:

For I = 1 to LenB(varArray)
Response.Write AscB(MidB(varArray,I,1))
Next