Centrum Skryptów - Systemy Operacyjne

Jak mogę określić, na który tydzień miesiąca przypada określona data? 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 mogę określić, na który tydzień miesiąca przypada określona data?

Cześć, Skrypciarzu! W jaki sposób mogę określić, na który tydzień miesiąca przypada określona data?

-- Ania

Cześć, Aniu. Najprawdopodobniej książka Moby Dick, w której opętany kapitan chce odszukać i zabić wielkiego, białego wieloryba, nie jest Ci obca. Bowiem, jak się okazuje, Twoje pytanie jest czymś w rodzaju Moby Dicka świata skryptów. Kiedy je przeczytaliśmy, zabraliśmy się za wertowanie dokumentacji języka VBScript, mając nadzieję, że znajdziemy tam funkcję o nazwie w rodzaju WeekOfTheMonth. Nie znaleźliśmy: funkcja taka nie istnieje. Przejrzeliśmy następnie grupy dyskusyjne, ale tam też nie było odpowiedzi. Wtedy byliśmy już tak sfrustrowani, że pragnienie znalezienia odpowiedzi praktycznie nas opętało.

Znaczy, prawie nas opętało: właściwie to nic w tej sprawie nie robiliśmy, tylko od czasu do czasu myśleliśmy sobie, że dobrze by było wreszcie coś wymyślić. Aż w końcu, przed paroma dniami, przysiedliśmy fałdów i spróbowaliśmy znaleźć rozwiązanie.

I rzeczywiście: udało nam się. Nie powiemy, żeby było to szczególnie eleganckie wyjście, i niewątpliwie istnieją wyjścia lepsze i wydajniejsze. Ale ważne że działa, a o to w końcu chodzi. (Wiadomo że zawsze te nieeleganckie typki wykłócają się, że elegancja jest bez znaczenia.)

Oto skrypt podający, na który tydzień miesiąca przypada 19 grudnia 2005 roku:

dtmTargetDate = #12/19/2005#   



dtmDay = DatePart("d", dtmTargetDate)

dtmMonth = DatePart("m", dtmTargetDate)

dtmYear = DatePart("yyyy", dtmTargetDate)



dtmStartDate = dtmMonth & "/1/" & dtmYear

dtmStartDate = CDate(dtmStartDate)



intWeekday = Weekday(dtmStartDate)

intAddon = 8 - intWeekday



intWeek1 = intAddOn

intWeek2 = intWeek1 + 7

intWeek3 = intWeek2 + 7

intWeek4 = intWeek3 + 7

intWeek5 = intWeek4 + 7

intWeek6 = intWeek5 + 7



If dtmDay <= intWeek6 Then

    strWeek = "Week 6"

End If



If dtmDay <= intWeek5 Then

    strWeek = "Week 5"

End If



If dtmDay <= intWeek4 Then

    strWeek = "Week 4"

End If



If dtmDay <= intWeek3 Then

    strWeek = "Week 3"

End If



If dtmDay <= intWeek2 Then

    strWeek = "Week 2"

End If



If dtmDay <= intWeek1 Then

    strWeek = "Week 1"

End If



Wscript.Echo strWeek

Skrypt ten jest troszkę skomplikowany, więc tutaj mamy miejsce tylko na pobieżny opis jego działania; wszystkie soczyste szczególiki musicie wyciągnąć sami. Zauważmy również, że w skrypcie przyjmujemy, iż pierwszy tydzień miesiąca to ten, na który przypada pierwszy; nie zajmujemy się pierwszym pełnym tygodniem miesiąca ani pierwszym tygodniem z dniem roboczym, ani niczym podobnym. Jeśli Was to interesuje, jesteście zdani na siebie samych.

Przejdźmy jednak do rzeczy. Skrypt opiera się na założeniu, że kluczem do określenia tygodnia, na który przypada określona data jest określenie, w jaki dzień tygodnia zaczyna się miesiąc. Dlaczego? No cóż, załóżmy, że pierwszy przypada na sobotę. Wynika stąd, że drugi przypada na niedzielę, czyli – na nasze potrzeby – drugi dzień miesiąca to już drugi tydzień. Co się jednak stanie, jeśli pierwszy przypadnie na piątek? Drugi będzie sobotą, a to – znowu na nasze potrzeby – oznacza, że drugi dzień miesiąca mieści się w pierwszym tygodniu.

Pogubiliście się? Spójrzmy na kalendarz na grudzień 2005. Pierwszy, drugi i trzeci grudnia to tydzień pierwszy; czwarty grudnia to początek drugiego tygodnia:

Właściwości: Data i godzina

Z tego obrazka widzimy, że nasza data – 19 grudnia – mieści się w tygodniu czwartym. Jak to jednak określamy w języku skryptów?

Najpierw używamy funkcji DatePart języka VBScript by pobrać dzień (d), miesiąc (m), i rok (yyyy) naszej daty:

dtmDay = DatePart("d", dtmTargetDate)

dtmMonth = DatePart("m", dtmTargetDate)

dtmYear = DatePart("yyyy", dtmTargetDate)

Następnie tworzymy nową datę odpowiadającą pierwszemu grudnia 2005 roku, używając poniższego kodu:

dtmStartDate = dtmMonth & "/1/" & dtmYear

dtmStartDate = CDate(dtmStartDate)

W pierwszym wierszu składamy ciąg oznaczający datę (12/1/2005 – na sposób amerykański), w drugim zaś za pomocą funkcji CDate upewniamy się, że VBScript potraktuje ten ciąg jako oznaczenie daty. Nie jest chyba źle.

Ale teraz będzie gorzej. Korzystamy z funkcji Weekday (dzień tygodnia) by określić, na jaki dzień tygodnia przypada pierwszy grudnia:

intWeekday = Weekday(dtmStartDate)

Funkcja Weekday podaje liczbę całkowitą od 1 (niedziela) do 7 (sobota). Pierwszy grudnia to czwartek, uzyskujemy więc wartość 5.

Teraz musimy określić, jaka data oznaczać będzie ostatni dzień tygodnia pierwszego; to ważne, ponieważ na tej podstawie będziemy mogli określić końcowe dni wszystkich tygodni. Kiedy będziemy to wiedzieć, wydedukowanie na który tydzień przypada dana data nie będzie już problemem. Końcową datę pierwszego tygodnia określimy dzięki poniższemu fragmentowi kodu:

intAddon = 8 - intWeekday

Czemu używamy tego kodu? Dobre pytanie. Kiedy spojrzymy na kalendarz, widzimy, że pierwszy grudnia to czwartek, który ma wartość 5. Kiedy odejmiemy 5 od 8, uzyskamy 3. Spójrzmy na kalendarz ponownie: trzeci grudnia to ostatni dzień tygodnia pierwszego. Czyli wystarczy odjąć wartość Weekday od 8 aby poznać, kiedy wypada ostatni dzień pierwszego tygodnia.

Tak, jasne. Ale popróbujcie, a zobaczycie że działa.

Teraz, kiedy juz wiemy, że pierwszy tydzień kończy się trzeciego grudnia, możemy bez trudu wyliczyć daty końcowe pozostałych tygodni; tydzień drugi kończyć się będzie 3+7 grudnia, czyli dziesiątego. Według tego wzoru miesiąc może mieć nawet sześć tygodni, więc obliczamy sześć dat końcowych (to, że większość miesięcy nie będzie miało aż tylu tygodni nie ma w tej chwili znaczenia):

intWeek1 = intAddOn

intWeek2 = intWeek1 + 7

intWeek3 = intWeek2 + 7

intWeek4 = intWeek3 + 7

intWeek5 = intWeek4 + 7

intWeek6 = intWeek5 + 7

Następną część moglibyśmy trochę skrócić, ale chcieliśmy, by jasne było, co się dzieje, więc zapisaliśmy ją w postaci instrukcji If-Then. Określiliśmy już wcześniej dzień naszej daty: 19. Teraz zaś określiliśmy jeszcze daty końcowe każdego tygodnia w miesiącu:

TydzieńData końcowa
638
531
423
317
210
13

Kolejny krok polega na sprawdzeniu, czy wartość naszego dnia – 19 – jest mniejsza lub równa wartościom dat końcowych poszczególnych miesięcy. Czy 19 to mniej niż wartość daty końcowej tygodnia 6, czyli 38? Tak, zatem ustalamy wartość zmiennej strWeek jako „Week 6” – tydzień 6. Czy 19 to mniej niż 31 – data końcowa tygodnia 5? Tak, teraz zatem zmieniamy wartość zmiennej strWeek na „Week 5”. A jak się sprawy mają z tygodniem 4? Podobnie, więc wartość zmiennej strWeek zmienia się na „Week 4”. Jasne?

Ok, więc teraz przechodzimy do tygodnia 3. Czy liczba 19 jest mniejsza lub równa 17? Nie, tak więc nie zmieniamy już wartości zmiennej strWeek. Kiedy skończymy z instrukcjami If-Then, wywołujemy echo wyników: okazuje się że 19 grudnia 2005 r. wypada w czwartym tygodniu miesiąca.

Znowu przedstawiamy pobieżny opis dość skomplikowanego skryptu, za co przepraszamy. Ale przynajmniej skrypt działa. I chociaż wygląda bardzo dziwnie, to i tak łatwiej było go napisać niż upolować wielkiego, białego wieloryba (nawet jeśli chodzi o obsesje, idziemy zawsze po linii najmniejszego oporu)

 Do początku strony Do początku strony


Centrum Skryptów - Systemy Operacyjne