2013-02-19 15 views
5

Ich habe die folgende Funktion, die bei der Konvertierung der aktuellen Zeit in UTC-Zeit gut funktioniert.Konvertieren Sie Zeit in UTC vbScript

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 

aber ich denke, dass dies angemessen behandelt nicht Umwandlung der Zukunft oder historischen Daten zu UTC, da die Funktion den Versatz des Servers Zeitzone zum Zeitpunkt des Datums wissen müßte, das konvertiert wird und ob es während der Sommerzeit war oder nicht.

Wie kann ich das umgehen?

ich auf Windows-Server mit IIS7.5

vbScript/Classic ASP bin mit Um zu klären, das hat nichts mit der Formatierung das Datum zu tun. Es geht darum, aus der Server-Zeitzone für historische Daten in UTC zu konvertieren. Während der Sommerzeit ist der Offset um 60 Minuten aus, wenn ich versuche, eine Datetime zu konvertieren, die in Standardzeit aufgetreten ist)

Zum Beispiel: Sagen wir, dass heute, 2013-02-19 (keine Sommerzeit), Ich möchte einen Zeitstempel von sagen, 2008-06-05 (während der Sommerzeit) von PDT (meine Server Zeitzone) zu UTC. Die Verwendung der Methode in meiner Funktion gibt mir einen Wert, der um 60 Minuten vom korrekten Wert abweicht (da die AKTUELLE Zeit PST (nicht PDT) ist, ist der Offset für dieses historische Datum falsch).

+1

Da Sie Javascript auch serverseitig verwenden können, würde ich vorschlagen, dass Sie javascripts toUTCString() verwenden – AardVark71

+0

Danke @ AardVark71, habe ich nicht an diese Option gedacht. Ich werde einige Unit-Tests machen und sehen, wie es herauskommt, und Sie wissen lassen, wie es sich entwickelt. – GWR

+0

Funktioniert wie ein Charme. Ich werde meine endgültige Lösung in einigen veröffentlichen. – GWR

Antwort

4

Hier ist die Lösung, die ich auf Vorschlag von @ AardVark71 implementiert habe.

Ich habe dies in meine Funktion eingefügt.asp-Datei:

<script language="javascript" runat="server"> 
    function toUtcString(d) { 
     var dDate = new Date(d); 
     return Math.round(dDate.getTime()/1000); 
    }; 
</script> 

Es gibt einen Timestamp-Wert aus. Dann von überall in dem klassischen ASP-Code, kann ich dies tun:

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 

Diese (glaube ich) ist einfach, und es produziert die erwarteten Werte und voll Faktoren in der DST.

+0

Dies funktioniert nicht für Zeitstempel mit Werten größer als Untertyp Long. z.B. DateAdd ("s", toUtcString (cDate ("01/01/2060 06: 25 PM")), "01/01/1970 00:00:00") – ulluoink

+0

Dies funktioniert nicht für ISO8601-Daten. Auf Server laufen, neues Datum ("2015-08-27T12: 28: 51") zurück NaN Beim Client laufen Thu Aug 27 2015 11:58:16 GMT + 0200 Ich wollte UTC in Ortszeit konvertieren. –

0

Wenn ich etwas nicht vermisse, müssen Sie lokale Zeit auf Remote-Rechner bekommen und es Zeitzone Offset, oder?

Here Ich sehe selbst Antwort basierend auf WMI Win32_TimeZone Bias Eigenschaft. Aber nach diesem MSDN Beispiel: „Converting Local Time to UTC Time“, Zitat:

Verwenden Win32_ComputerSystem Current Eigenschaft, weil es automatisch die Zeitzone Bias für die Sommerzeit einstellt Win32_TimeZone Bias Eigenschaft nicht.

So, nächste Beispiel Funktion erhalten aktuelle Datum Zeit, und ich werde Ihnen überlassen, um es für konkrete Datum Zeitmessung zu ändern.

' "." 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 

[EDIT] Nun, sieht aus wie nicht dann auf MSDN vertrauen sollte (oder vielleicht diese Arbeit nur für aktuelle Zeit). Ich sehe jedoch, dass es nicht die Antwort ist, nach der Sie suchen. Wenn Sie keine bessere Idee finden, können Sie dies automatisieren online calculator.

P.S. Ok, streichen Sie den obigen Code aus und versuchen Sie es mit einer anderen "Iteration".

Nur um zu bemerken, dass ich einen Code mit meiner Zeitzone (Bulgarien) kompatibel gemacht habe, wo PDT am letzten Sonntag im März beginnt und am letzten Sonntag im Oktober endet. Dies erlaubt mir, meine PDT-Reichweite einfach einzustellen. Kurz gesagt, besteht die Idee darin, den Algorithmus auf Ihre Region anzuwenden. Der Rest ist klar, hoffe ich.

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 
+0

Ja, Sie vermissen das Hauptproblem - sagen Sie heute, 2013-02-19, ich möchte einen Zeitstempel von sagen, 2008-06-05 (während der Sommerzeit) von PDT (meine Server Zeitzone) zu UTC. Bei Verwendung der beschriebenen Methode erhalte ich einen Wert, der um 60 Minuten vom korrekten Wert abweicht (da die aktuelle Zeit PST (nicht PDT) ist, ist der Offset für dieses historische Datum falsch). – GWR

+0

Warten Sie eine Minute, warum verwenden Sie CURRENT Zeit? Ich dachte, du könntest die Idee aus meinem Knochen herausstreichen und den Rest erledigen, oder brauchst du mehr Hilfe? –

+0

Was ich unter "aktuell" verstehe, ist, dass Ihre wmi-Abfrage den Offset zum Zeitpunkt zurückgibt, an dem Sie sie angefordert haben. Dieser Offset könnte sich von dem Offset zum Zeitpunkt der Konvertierung unterscheiden. – GWR

Verwandte Themen