Centrum Skryptów - Systemy operacyjne

Jak przekonwertować wartość pacyficznego czasu standardowego na czas lokalny?

Udostępnij na: Facebook

Skrypciarze odpowiadają na Wasze pytania

Cześć Skrypciarze!

Witamy w rubryce TechNet, w której Skrypciarze z firmy Microsoft odpowiadają na częste pytania dotyczące używania skryptów w administracji systemu. Jeśli macie jakieś pytania z tej dziedziny, zachęcamy do wysłania e-maila na adres: scripter@microsoft.com. Nie możemy zagwarantować odpowiedzi na każde otrzymane pytanie, ale staramy się jak możemy.

Jak przekonwertować wartość pacyficznego czasu standardowego na czas lokalny?

Cześć Skrypciarze! Pytanie

Cześć, Skrypciarze! Zimowa Olimpiada Skrypciarska 2007 dostarczyła mi wielu wrażeń, ale jedna rzecz mnie w tym wszystkim trochę zastanowiła. Dlaczego podano terminy wszystkich zdarzeń, używając czasu Redmond? Rozumiem, że nie można podawać terminów, stosując wszystkie czasy lokalne na świecie; ale wiele osób mogłoby skorzystać ze skryptu, który konwertuje wartość czasu Redmond na swój czas lokalny. Czy są jakieś szanse otrzymania takiego skryptu przed Zimową Olimpiadą Skrypciarską 2008?

-- OD

Cześć Skrypciarze! Pytanie

Cześć, OD. Biorąc pod uwagę fakt, że pytanie to zostało do nas przesłane ponad rok temu, ktoś mógłby pomyśleć, że na pewno o nim zapomnieliśmy. Chcę jednak wszystkich zapewnić, że Skrypciarze rzadko, jeżeli w ogóle, o czymś zapominają. Nie zawsze reagują od razu, tak się przecież nie da, ale nigdy nie zapominają.

A nawet gdybyśmy o czymś zapomnieli, nasza Redaktorka nie omieszka nam o tym przypomnieć w charakterystyczny sobie sposób. Jest w tym naprawdę dobra.

Zatem nie, nie zapomnieliśmy o tym pytaniu, czekaliśmy na odpowiedni moment, żeby na nie odpowiedzieć. I chyba już najwyższy czas.

Oto skrypt, który konwertuje czas Redmond na czas lokalny:

strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")



Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")



For Each objTime in colTime

    intBias = objTime.Bias

Next



dtmRedmondTime = #2/19/2008 3:00 PM#

dtmGreenwichTime = DateAdd("n", 480, dtmRedmondTime)

dtmLocalDeadline = DateAdd("n",intBias, dtmGreenwichTime)



Wscript.Echo dtmLocalDeadline

Ten skrypt nie jest szczególnie trudny, ale jest w nim kilka rzeczy, które mogą sprawić problem.

Zobaczmy teraz, jak on działa. Zaczynamy od połączenia się z usługą WMI na lokalnym komputerze. Czy możemy uruchomić ten skrypt także na zdalnym komputerze? Pewnie, chociaż jeżeli zdalny komputer znajduje się w tej samej strefie czasowej co komputer lokalny, uruchamianie tego skryptu na tym zdalnym komputerze nie ma większego sensu. Jeżeli jednak naprawdę chcecie uruchomić skrypt na komputerze zdalnym, wystarczy przypisać nazwę tegoż komputera do zmiennej o nazwie strComputer:

strComputer = "atl-ws-001"

Po połączeniu się z usługą WMI używamy następującego wiersza kodu w celu pobrania kolekcji wszystkich stref czasowych, do których należy komputer:

Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")

Zauważcie, że komputer może należeć wyłącznie do jednej strefy czasowej. Dlatego ta kwerenda przekaże nam tylko jeden element.

Nawiasem mówiąc fakt, że Win32_TimeZone przekazuje tylko jeden element, sprawia że jest to klasa pojedyncza.

Po wysłaniu kwerendy uruchamiamy pętlę For Each, która przejdzie przez każdy element w kolekcji. Wiem, wiem: ponieważ Win32_TimeZon to klasa pojedyncza, zawiera tylko jeden element. Niemniej jednak kolekcja to kolekcja i w dalszym ciągu konieczne jest zastosowanie pętli For Each, która przez nią przejdzie, niezależnie od liczby elementów zawartych w tej kolekcji.

Uwaga: Przynajmniej tak było do tej pory. W systemie Windows Vista jednakże możliwy jest bezpośredni dostęp do elementu kolekcji, bez potrzeby stosowania pętli For Each. Więcej informacji na ten temat znajduje się w artykule WMI Indexer (j.ang.) w Centrum Skryptów.

Wewnątrz pętli For Each robimy tylko jedną rzecz: pobieramy wartość właściwości Bias i zachowujemy ją w zmiennej o nazwie intBias:

intBias = objTime.Bias

Czym jest właściwość Bias (odchylenie)? Cóż, ta właściwość informuje nas o różnicy (wyrażonej w minutach) pomiędzy czasem lokalnym a czasem UTC. To wyjaśnienie oficjalne SDK; w praktyce właściwość Bias informuje nas o różnicy (w minutach) pomiędzy czasem lokalnym a czasem uniwersalnym Greenwich. Przykładowo, kiedy w Londynie jest godz. 10:00 AM (Południk zerowy (j.ang.)), w Redmond jest 2:00 AM. Czas Redmont jest cofnięty o 8 godzin w stosunku do czasu uniwersalnego Greenwich, co oznacza, że strefa czasowa pacyficznego czasu standardowego ma właściwość Bias równą 480 minut.

Ale dlaczego musimy znać wartość właściwości Bias dla lokalnej strefy czasowej? Zaraz to wyjaśnię.

Zanim jednak do tego przejdziemy, musimy utworzyć wartość daty i godziny reprezentującą datę i godzinę w Redmond. Przykładowo, jeżeli termin dla określonego wydarzenia (przykładowo wydarzenia Olimpiady Skrypciarskiej) to 19 luty 2008, godz. 3:00 PM, możemy utworzyć wartość daty i godziny dla tego terminu, używając następującego wiersza kodu:

dtmRedmondTime = #2/19/2008 3:00 PM#
Uwaga: Do czego służą znaki funta (#) otaczające naszą wartość daty i godziny? To pomaga zagwarantować, że skrypt VBScript potraktuje tę wartość jako datę, a nie jako ciąg.

Teraz przechodzimy do poniższego wiersza kodu:

dtmGreenwichTime = DateAdd("n", 480, dtmRedmondTime)

Co tutaj robimy? Cóż, używamy funkcji DateAdd w celu dodania 480 minut do wartości daty i godziny, którą właśnie utworzyliśmy. (Podczas pracy z funkcją DateAdd parametr „n” reprezentuje minuty. Nie należy używać „m” w celu dodania minut. Parametr „m” spowodowałby dodanie 480 miesięcy, a nie 480 minut.). Dlaczego dodajemy 480 minut do naszej wartości daty i godziny czasu Redmond? No cóż, jak zauważyliśmy wcześniej, czas Redmond jest cofnięty o 8 godzin względem czasu uniwersalnego Greenwich. Aby przekonwertować czas Redmond na czas uniwersalny Greenwich musimy dodać do niego 8 godzin (480 minut).

Dlaczego w ogóle konwertujemy czas Redmond na czas uniwersalny Greenwich? Bezpośrednia konwersja czasu z jednej strefy czasowej na drugą może przysporzyć pewnych problemów. Wynika to z tego, że niektóre strefy czasowe mają ujemną wartość odchylenia (Bias) (np. -480), a inne dodatnią (np. 120). Zamiast zajmować się tymi wartościami zdecydowaliśmy wykonać tę procedurę w dwóch etapach: konwertujemy czas Redmond na jego ekwiwalent czasu uniwersalnego Greenwich, a następnie konwertujemy czas Greenwich na nasz czas lokalny. Jest to dodatkowy krok, ale prostszy do ujęcia w postaci kodu. Ponadto można go sobie o wiele łatwiej wyobrazić.

Zgodnie z zapowiedzią konwertujemy czas uniwersalny Greenwich na nasz czas lokalny. W tym celu użyjemy następującego wiersza kodu:

dtmLocalDeadline = DateAdd("n",intBias, dtmGreenwichTime)

Tym razem dodajemy (lub odejmujemy, jeżeli mamy ujemną wartość odchylenia) minuty do czasu Greenwich. Ile minut dodajemy? Prawdę mówiąc, nie wiem. Polegamy w tej kwestii na zmiennej intBias.

Widzicie jak to działa? Zaczynamy od następującej wartości czasu Redmond:

2/19/2008 3:00 PM

Po przekonwertowaniu tej wartości na czas uniwersalny Greenwich otrzymujemy następującą wartość:

2/19/2008 11:00 PM

Następnie używamy wartości odchylenia naszej strefy lokalnej w celu przekonwertowania czasu Greenwich na czas lokalny. Załóżmy, że mieszkamy w Atenach, w Grecji. Ateny są o 2 godziny do przodu względem czasu Greenwich. Oznacza to, że mają odchylenie o wartości 120 minut. Jeżeli dodamy 120 minut do naszego czasu Greenwich otrzymamy następującą wartość:

2/20/2008 1:00 AM

Innymi słowy, kiedy w Redmond jest godzina 3:00 PM w poniedziałek, w Atenach jest wtorek, godzina 1:00 AM. W ten właśnie sposób odbywa się konwersja terminów wyrażonych za pomocą pacyficznego czasu standardowego na terminy wyrażone w czasie lokalnym. Można to zrobić niezależnie od lokalizacji.

Przy okazji, jeżeli kiedykolwiek będziecie potrzebowali poznać czas aktualny w Redmond, możecie zastosować poniższy skrypt:

strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")



For Each objTime in colTime

    intBias = objTime.Bias

    intBias = intBias * -1

Next



dtmLocalTime = Now

dtmGreenwichTime = DateAdd("n", intBias, dtmLocalTime)

dtmRedmondTime = DateAdd("n", -480, dtmGreenwichTime)



Wscript.Echo dtmRedmondTime

Co dokładnie robi ten skrypt? Najpierw wykorzystuje funkcję Now w celu pobrania aktualnej daty i godziny, a następnie stosuje poniższy wiersz kodu oraz wartość odchylenia strefy czasowej w celu przekonwertowania aktualnej daty i godziny na Czas uniwersalny Greenwich:

dtmGreenwichTime = DateAdd("n", intBias, dtmLocalTime)

Zauważcie, że w naszej pętli For Each pomnożyliśmy wartość zmiennej intBias przez -1. Dlaczego? Ponieważ nie musimy już konwertować czasu Greenwich na czas lokalny, jak w pierwszym skrypcie. Konwertujemy natomiast wartość czasu lokalnego na czas Greenwich. Ponieważ odwróciliśmy kierunek, musimy odwrócić znak, przekształcając przykładowo wartość odchylenia 120 minut na -120 minut.

Na koniec dodajemy wartość -480 minut do Czasu uniwersalnego Greenwich w celu określenia wartości czasu w Redmond:

dtmRedmondTime = DateAdd("n",-480, dtmGreenwichTime)

Jeżeli w Atenach jest godzina 7:43 AM dnia 20 lutego, powinniśmy otrzymać następującą wartość czasu Redmond:

2/19/2008 9:43 PM

Ciekawe, nieprawdaż?

À propos, jeżeli to wszystko wydaje się zbyt skomplikowane, istnieje pewna alternatywa: możecie zajrzeć na tę stronę (j.ang), na której umieściliśmy terminy wydarzeń (8:00 AM dla głównych wydarzeń olimpiady Skrypciarskiej oraz 3:00 PM dla kategorii Sudden Death Challenge) przekonwertowane na czasy lokalne dla różnych miast i stref czasowych na całym świecie.

Przyznaję, że o wiele prościej byłoby od razu pokazać Wam tę stronę, zamiast pisać skrypty (i cały artykuł). Ale w końcu na tym polega zabawa. A skoro znowu mówimy o skryptach, to czy odliczacie już minuty do rozpoczęcia Olimpiady? Zakładając, że oficjalne rozpoczęcie Olimpiady nastąpi o godz. 8:00 AM PST w piątek 15 lutego 2008 możecie wykorzystać następujący skrypt, który poinformuje Was o tym, ile minut zostało:

strComputer = "."



Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")

Set colTime = objWMIService.ExecQuery("Select * From Win32_TimeZone")



For Each objTime in colTime

    intBias = objTime.Bias

    intBias = intBias * -1

Next



dtmLocalTime = Now

dtmGreenwichTime = DateAdd("n", intBias, dtmLocalTime)

dtmRedmondTime = DateAdd("n", -480, dtmGreenwichTime)



dtmOpeningDay = #2/15/2008 8:00 AM#



Wscript.Echo DateDiff("n", dtmRedmondTime, dtmOpeningDay)

Zatem do zobaczenia już niebawem. Mam nadzieję, że znacie już dokładną godzinę rozpoczęcia Olimpiady. Jeżeli nie, zajrzyjcie na tę stronę sieci Web (j.ang.). Życzę wszystkim powodzenia!

 Do początku strony Do początku strony

Centrum Skryptów - Systemy operacyjne