我有以下功能,可以将当前时间转换为UTC时间。
Function toUtc(byVal dDate)
Dim oShell : Set oShell = CreateObject("WScript.Shell")
toUtc = dateadd("n", oShell.RegRead("HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\TimeZoneInformation\ActiveTimeBias"), cDate(dDate))
End Function
但是,我认为这不能充分处理将来或历史日期转换为UTC,因为该函数需要知道转换日期时服务器时区的偏移量,以及是否或不是在白天节省时间。
我怎样才能解决这个问题?
我在带有IIS7.5的Windows服务器上使用vbScript / Classic ASP
澄清一下,这与格式化日期无关。它是关于从服务器时区转换为UTC历史日期的全部内容。在夏令时期间,如果我尝试转换标准时间内发生的日期时间,则偏移量将减少60分钟。
例如:
让我们说今天,2013-02-19(非夏令时),我想把时间戳从2008-06-05(夏令时期间)从PDT(我的服务器时区)转换为UTC 。使用我函数中的方法将给出一个与正确值相差60分钟的值(因为当前时间是PST(不是PDT),该历史日期的偏移量将不正确)。
换句话说,输入日期的时区偏移量可以是UTC-7或UTC-8,具体取决于是否在该特定日期观察到DST。我需要计算输入日期的正确UTC日期,无论是否在当前日期观察到DST,我都需要使用该代码。
答案 0 :(得分:4)
这是我在@AardVark71的建议下最终实现的解决方案。
我把它放在我的func.asp文件中:
<script language="javascript" runat="server">
function toUtcString(d) {
var dDate = new Date(d);
return Math.round(dDate.getTime() / 1000);
};
</script>
它输出时间戳值。然后从经典的asp代码中的任何地方,我都可以这样做:
response.Write DateAdd("s", toUtcString(cDate("11/11/2012 06:25 PM")), "01/01/1970 00:00:00") 'expect 11/11/2012 10:25:00 PM gmt/utc time
response.Write DateAdd("s", toUtcString(cDate("06/11/2012 06:25 PM")), "01/01/1970 00:00:00") 'expect 6/11/2012 9:25:00 PM gmt/utc time
这(我相信)很简单,它会在DST中产生预期值和完全因子。
答案 1 :(得分:1)
在ASP classic中,您可以在一个页面内混合使用VBScript和JScript代码。 JScript Date
对象可用于本地⇄UTC日期转换。完整的例子:
<%@ language="vbscript" %>
<%
Option Explicit
Dim local_date
Dim utc_date
For Each local_date In Array("11/11/2012 06:25 PM", "06/11/2012 06:25 PM")
utc_date = local_to_utc(local_date)
Response.Write "Local: " & local_date & ", UTC: " & utc_date & vbNewLine
Next
For Each utc_date In Array("2012-11-12T02:25:00Z", "2012-06-12T01:25:00+00:00")
local_date = utc_to_local(utc_date)
Response.Write "UTC: " & utc_date & ", Local: " & local_date & vbNewLine
Next
%>
<script language="jscript" runat="server">
function local_to_utc(datestr) {
// note that this function lets JScript engine parse the date, correctly or otherwise
var date = new Date(datestr);
var result = date.getUTCFullYear() + "-" + (date.getUTCMonth() + 1) + "-" + date.getUTCDate() + "T" + date.getUTCHours() + ":" + date.getUTCMinutes() + ":" + date.getUTCSeconds();
return result.replace(/(\D)(\d)(?!\d)/g, "$10$2") + "Z";
}
function utc_to_local(datestr) {
// note that this function parses only a subset of ISO 8601 date format
var match = datestr.match(/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(?:\.(\d{3}))?(?:Z|([-+])(\d{2}):(\d{2}))$/);
var offset = match[8] ? (match[8] === "+" ? 1 : -1) * (match[9] * 60 + match[10] * 1) : 0;
var date = new Date(Date.UTC(match[1], match[2] - 1, match[3], match[4], match[5] - offset, match[6], match[7] || 0));
var result = date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate() + " " + date.getHours() + ":" + date.getMinutes() + ":" + date.getSeconds();
return result.replace(/(\D)(\d)(?!\d)/g, "$10$2");
}
</script>
预期结果:
使用PST / PDT时间在服务器上执行时的输出:
Local: 11/11/2012 06:25 PM, UTC: 2012-11-12T02:25:00Z
Local: 06/11/2012 06:25 PM, UTC: 2012-06-12T01:25:00Z
UTC: 2012-11-12T02:25:00Z, Local: 2012-11-11 18:25:00
UTC: 2012-06-12T01:25:00+00:00, Local: 2012-06-11 18:25:00
答案 2 :(得分:0)
如果我没有错过任何东西,你需要在远程机器上获得当地时间和时区偏移,对吗?
Here我看到基于WMI Win32_TimeZone Bias
属性的自我回答。但根据MSDN示例:“Converting Local Time to UTC Time”,引用:
使用Win32_ComputerSystem CurrentTimeZone属性,因为它 自动调整夏令时的时区偏差 Win32_TimeZone偏置属性没有。
因此,下一个示例函数获取当前日期时间,我将留给您修改具体的日期时间。
' "." mean local computer
WScript.Echo FormatDateTime(UTCDate("."), 0)
Function UTCDate(strComputer)
Dim objWMIService, ColDate, ColCS
On Error Resume Next
Set objWMIService = _
GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set ColDate = objWMIService.ExecQuery("Select * From Win32_LocalTime")
UTCDate = DateSerial(100, 1, 1)
For Each objDate In ColDate
UTCDate = DateAdd("yyyy", ObjDate.Year - 100, UTCDate)
UTCDate = DateAdd("m", ObjDate.Month - 1, UTCDate)
UTCDate = DateAdd("d", ObjDate.Day - 1, UTCDate)
UTCDate = DateAdd("h", ObjDate.Hour, UTCDate)
UTCDate = DateAdd("n", ObjDate.Minute, UTCDate)
UTCDate = DateAdd("s", ObjDate.Second, UTCDate)
Next
' http://msdn.microsoft.com/en-us/library/windows/desktop/ms696015(v=vs.85).aspx
Set ColCS = objWMIService.ExecQuery("Select * From Win32_ComputerSystem")
Dim TimeZoneOffset, LocalTimeZone
For Each LocalTimeZone In ColCS
TimeZoneOffset = LocalTimeZone.CurrentTimeZone
Next
If TimeZoneOffset < 0 Then
TimeZoneOffset = Abs(TimeZoneOffset)
Else
TimeZoneOffset = -Abs(TimeZoneOffset)
End If
UTCDate = DateAdd("n", TimeZoneOffset, UTCDate)
If Err Then UTCDate = vbNull
Set objWMIService = Nothing
End Function
[编辑]好吧,看起来不应该信任MSDN(或者这可能仅适用于当前时间)。但是,我发现这不是你要找的答案。如果您没有找到更好的主意,可以自动执行此online calculator。
P.S。好的,敲击上面的代码然后尝试另一个“迭代”。
请注意,我制作的代码与我的时区(保加利亚)兼容,PDT从3月的最后一个星期日开始,到10月的最后一个星期日结束。这让我可以轻松设置我的PDT范围。不久,我们的想法是使算法适用于您所在的地区。其余的显然是,我希望。
With New DateDrill
Debug.WriteLine .UTCDate("2008-6-28")
Debug.WriteLine .UTCDate("2014-1-21")
End With
Class DateDrill
Public Function UTCDate(ByVal dtDate)
If Not IsDate(dtDate) Then Err.Raise 5
dtDate = CDate(dtDate)
Dim ZoneBias: ZoneBias = TimeZoneBias()
If IsPDT(Now) <> IsPDT(dtDate) Then
ZoneBias = ZoneBias - 60
End If
UTCDate = DateAdd("n", ZoneBias, dtDate)
End Function
Private Function IsPDT(ByVal dtDate)
If Not IsDate(dtDate) Then Err.Raise 5
dtDate = CDate(dtDate)
Dim pdtLow, pdtUpr, nDaysBack
pdtLow = DateSerial(Year(dtDate), 3, 31)
pdtUpr = DateSerial(Year(dtDate), 10, 31)
pdtLow = DateAdd("h", 2, pdtLow)
pdtUpr = DateAdd("h", 2, pdtUpr)
nDaysBack = Weekday(pdtLow) - 1
If nDaysBack <> 0 Then
pdtLow = DateAdd("d", -nDaysBack, pdtLow)
End If
nDaysBack = Weekday(pdtUpr) - 1
If nDaysBack <> 0 Then
pdtUpr = DateAdd("d", -nDaysBack, pdtUpr)
End If
IsPDT = (dtDate >= pdtLow And dtDate <= pdtUpr)
End Function
Private Function TimeZoneBias()
Dim LTZone
With GetObject("winmgmts:" & _
"{impersonationLevel=impersonate}!\\.\root\cimv2")
For Each LTZone In .ExecQuery(_
"Select * From Win32_ComputerSystem")
TimeZoneBias = LTZone.CurrentTimeZone
Next
End With
TimeZoneBias = TimeZoneBias * -1
End Function
End Class
答案 3 :(得分:0)
这个少量的ASP VBScript函数可以满足您的需要。我正在从MySQL数据库绘制Unix时间戳。根据您的数据库,查询可能会稍有不同,但是大多数DB可以返回Unix时间戳。在我的服务器上,查询只需要一到两毫秒。
注意:pquery
是我自己的用于运行SQL查询的函数。显然可以替代您自己的方法。
每次unixTime()
运行时,我都在计算偏移量。当然,您可以在“ bootstrap”文件中计算一次,并根据需要设置全局变量。
Function unixTimestamp()
' Unix Timestamp, drawn from MySQL because ASP doesn't natively handle time zones
rs = pquery( "SELECT unix_timestamp() AS `ts`", null )
unixTimestamp = cLng( rs("ts") )
End Function
Function utc_offset()
' Offset of Server time from UTC, in seconds
dim unixNow : unixNow = unixTimestamp()
dim aspNow : aspNow = cLng( DateDiff( "s", "01/01/1970 00:00:00", now() ) )
utc_offset = cLng( ( aspNow - unixNow ))
End Function
Function unixTime( byVal dt )
dim offset : offset = utc_offset()
if( VarType( dt ) = vbDate ) then
unixTime = cLng( DateDiff( "s", "01/01/1970 00:00:00", dt ) - offset )
else
if( isDate( dt ) ) then
dt = cDate( dt )
unixTime = cLng( DateDiff( "s", "01/01/1970 00:00:00", dt ) - offset )
else
unixTime = null
end if
end if
End Function
Function datetimeFromUnix( byVal udt, offset )
datetimeFromUnix = cDate( DateAdd( "s", udt + offset , "01/01/1970 00:00:00" ) )
End Function
现在运行:
utcTimestamp = unixTime( dDate )
utcDate = datetimeFromUnix( utcTimestamp, 0 ) ' UTC
localDate = datetimeFromUnix( utcTimestamp, utc_offset() ) ' back where we started