[ direktsprung: Script DATING.BAT - Literatur - Excel-Lösung CALWEEK ]

DATING.BAT

Die Wochennummer. Da ist sie. Mit Kollegen.

Du brauchst die Wochennummer eines Datums? Oder den Wochentag, den Tag des Jahres, oder die Elemente des Datums aufgesplittet? Dann brauchst Du mein kleines Batch-Skript DATING.BAT, das genau dies tut. Du suchst die Wochennummer in Excel? Schau' mal unten nach, da findest Du ein AddIn für Excel von Thomas WEBER, das Du als Ausgangspunkt benutzen kannst.

Was ist da so schwierig dran?
Die Problematik der Wochennummer offenbart sich erst, wenn man sie braucht, zum Beispiel für Log-Files, die pro Woche in unterschiedlichen Verzeichnissen gespeichert werden sollen.

"Wie, Problematik?" fragst Du. "Gibt's da keinen Befehl für?"

Nein, auf einem puren Windows nicht. Klar, mit installiertem Perl oder Python oder ähnlichen Geschützen ist's ein Einzeiler, aber ohne solche Hilfsmittel geht's nicht so einfach. Nun sagst Du:

"So ein Skript läuft doch höchstens 30 Jahre, danach bin ich eh' auf'm Mars, warum also nicht die Wochennummern der kommenden 30 Jahre besorgen, in ein Textfile, und per find durchsuchen?"

Ganz einfach: Weil das kiki ist, und für kiki brauchen wir keine Computer, so sieht's aus. Es gibt eine ISO-Verordnung zur Wochennummer, also verbietet sich die Verwendung von Listen, sowas will berechnet werden ;-)

"Also gut, teilen wir das Datum durch 7, fertig. Öh... hm, oder den fortlaufenden Tag des Jahres durch 7, warte - da ziehen wir drei, ne, vier ab, wenn der Donnerstag nicht der Erste ist - halt, aber dieses Jahr ist ein Schaltjahr, dann noch eins runter, einen im Sinn, äh... einen Moment noch, hab's gleich..."

Ok, Du siehst, so easy ist's nicht ;-)) Lies' Dich durch die Literatur, dann wird Dir klar, warum da eine ISO-Verordnung für geschrieben wurde.

Wie geht das in Batch?
Die Berechnung benötigt gerade mal die vier Grundrechenarten + - * / und MOD b, was sich gerade in Batch hervorragend einfach als SET /A a - a / b * b darstellen lässt, da Batch nur in Integer rechnet. Gemerkt? SET /A rechnet! Die genaue Beschreibung der Berechnung erspare ich mir hier, sie findet sich in der unten angegebenen Literatur. Es werden am Ausgang der Berechnung Umgebungsvariablen gesetzt, die alle mit Curr beginnen. Der Schalter /print gibt sie am Ende der Berechnung mit aus. Bumm.

Wie installiere ich dating.bat?
Speichere das folgende Script als dating.bat irgendwo in Deinem %PATH% ab, %windir%\system32 ist ein guter Platz. Gib' dann an einer Kommandozeile dating /help ein. Und los geht's. Übrigens: Wenn Du das nicht hinkriegst, dann - ehrlich gesagt - brauchst Du die Wochennummer nicht wirklich in Scriptform. Ist nicht bös' gemeint.

Wie deinstalliere ich dating.bat?
Was ist das denn bitte schon wieder für 'ne Frage? ;) Wie wär's mit
del %windir%/system32/dating.bat ?

Viel Spaß wünscht

Robert Kehl

PS: Fragen und Anregungen sind gerne willkommen. Insbesondere, wenn Du Anregungen zur Simplifizierung des Codes hast, oder wie man das ein oder andere ganz einfach eleganter schreiben kann, freue ich mich über eine eMail.

::: dating.bat rel_1_0 (c) ROKNET.de
::: calculates some date related values from a given date
::: follows ISO 8601
:::
::: use and copy freely in its whole
::: please inform me about your changes, be nice
::: http://robertkehl.de/scriptoman/dating.htm
:::
::: !!CAVE: this is *not* (yet) bulletproofed
::
@echo off

SET _tmp_position=X:\path\to\dating.bat

IF /i "%~1" EQU "/help" GOTO Usage
IF /i "%~1" EQU "/?" GOTO Usage

IF /i "%~1" NEQ "/clear" GOTO C2
  ECHO Clearing all variables
  SET CurrDay=
  SET CurrMonth=
  SET CurrWeekDay=
  SET CurrWeekDayNumber=
  SET CurrWeekNumber=
  SET CurrYear=
  SET CurrDayNumber=
  GOTO Cleanup

:C2
IF /i "%~1" EQU "/source" (
  TYPE %_tmp_position%\dating.bat|MORE
  GOTO :EOF
)

IF "%~1" NEQ "" GOTO Beginn
ECHO *** Error: No Date given.
ECHO.

:Usage
SET _tmp_remmer=:
c:\winnt\system32\find /i "%_tmp_remmer%%_tmp_remmer%%_tmp_remmer%" %_tmp_position%\dating.bat
SET _tmp_remmer=
ECHO.
ECHO Usage:
ECHO   DATING.BAT options
ECHO.
ECHO where 'options' is one of:
ECHO   /help                - guess what?
ECHO   /source              - source code
ECHO or one or more of:
ECHO   /clear               - clears all variables
ECHO   date [/print [item]] - sets [and prints] dating environment variables
ECHO.
ECHO and 'date' is one of:
ECHO   today
ECHO   [dd ]DD.MM.YYYY
ECHO.
ECHO and 'item' is one of:
ECHO   Day
ECHO   Month
ECHO   WeekDay
ECHO   WeekDayNumber
ECHO   WeekNumber
ECHO   Year
ECHO   YearDayNumber
ECHO or an abbreviation of the above.
ECHO.
ECHO Examples:
ECHO   DATING.BAT today                               uses the current date
ECHO   DATING.BAT %%date%%                              same as above
ECHO   DATING.BAT %%date:~3%%                           same as above
ECHO   DATING.BAT So 09.03.2003 /print                with day (but won't be used)
ECHO   DATING.BAT 17.06.1985 /print WeekNumber        just the Weeknumber
ECHO   DATING.BAT 31.12.2197 /print " %&set _tmp_"     prints all variables
ECHO   DATING.BAT today /print "yeard %&set currweekn" Two values
 ECHO.
ECHO Thank goes out to the people who maintain the following websites:
ECHO   http://66.39.60.58/y2k.html
ECHO   http://zijlema.basicguru.com/weeknbr.html
ECHO   http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm
ECHO   http://utopia.knoware.nl/~ocorten/timex/wkcalc.htm
ECHO   http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt
ECHO   http://www.fpschultze.de/batstuff.html
ECHO   http://www.robvanderwoude.com/index.html
ECHO.
ECHO Remember: Information wants to and should always be free!

GOTO :EOF

:Beginn
SET _tmp_Given=%*

IF "%_tmp_Given:~0,5%" EQU "today" SET _tmp_P=%date:~3%

IF DEFINED _tmp_P GOTO Easy
SET _tmp_f2=%_tmp_Given:~0,2%
SET /A _tmp_f2=%_tmp_Given% 2>NUL:
IF "%_tmp_f2%" EQU "0" (SET _tmp_P=%_tmp_Given:~3%) ELSE SET _tmp_P=%*

:Easy
SET CurrDay=%_tmp_P:~0,2%
SET _tmp_F=%CurrDay:~0,1%
IF %_tmp_F% EQU 0 SET CurrDay=%_tmp_P:~1,1%

SET CurrMonth=%_tmp_P:~3,2%
SET _tmp_F=%CurrMonth:~0,1%
IF %_tmp_F% EQU 0 SET CurrMonth=%_tmp_P:~4,1%

SET CurrYear=%_tmp_P:~6,4%

:: Number of Day in Year
SET /A CurrDayNumber = ( CurrMonth - 1 ) * 30 + CurrDay
IF %CurrMonth% GTR 1 SET /A CurrDayNumber += 1
IF %CurrMonth% GTR 2 SET /A CurrDayNumber -= 2
IF %CurrMonth% GTR 3 SET /A CurrDayNumber += 1
IF %CurrMonth% GTR 5 SET /A CurrDayNumber += 1
IF %CurrMonth% GTR 7 SET /A CurrDayNumber += 1
IF %CurrMonth% GTR 8 SET /A CurrDayNumber += 1
IF %CurrMonth% GTR 10 SET /A CurrDayNumber += 1

:: Leap CurrYear
SET /A _tmp_4 = CurrYear - CurrYear / 4 * 4
SET /A _tmp_100 = CurrYear - CurrYear / 100 * 100
SET /A _tmp_400 = CurrYear - CurrYear / 400 * 400
SET _tmp_CYisLeap=
IF %_tmp_4% NEQ 0 GOTO LeapLastYear
IF %_tmp_100% EQU 0 IF %_tmp_400% NEQ 0 GOTO LeapLastYear
SET _tmp_CYisLeap=1
IF DEFINED _tmp_CYisLeap IF %CurrMonth% GTR 2 SET /A CurrDayNumber += 1

:LeapLastYear
SET _tmp_LYisLeap=
SET /A _tmp_LY = CurrYear - 1
SET /A _tmp_4 = _tmp_LY - _tmp_LY / 4 * 4
SET /A _tmp_100 = _tmp_LY - _tmp_LY / 100 * 100
SET /A _tmp_400 = _tmp_LY - _tmp_LY / 400 * 400
SET _tmp_LYisLeap=
IF %_tmp_4% NEQ 0 GOTO NWY1
IF %_tmp_100% EQU 0 IF %_tmp_400% NEQ 0 GOTO NWY1
SET _tmp_LYisLeap=1

:NWY1
SET /A _tmp_YY=(CurrYear-1)-(CurrYear-1)/100*100
SET /A _tmp_C=((CurrYear-1)-_tmp_YY)/100
SET /A _tmp_G=_tmp_YY+_tmp_YY/4
SET /A _tmp_01=1+(((((_tmp_C)-(_tmp_C)/4*4)*5)+_tmp_G)-((((_tmp_C)-(_tmp_C)/4*4)*5)+_tmp_G)/7*7)

:: Number of Week Day
SET /A CurrWeekDayNumber=1+(((CurrDayNumber+(_tmp_01-1))-1)-((CurrDayNumber+(_tmp_01-1))-1)/7*7)

:: Name of Week Day
SET CurrWeekDay=Mo
IF %CurrWeekDayNumber% == 2 SET CurrWeekDay=Di
IF %CurrWeekDayNumber% == 3 SET CurrWeekDay=Mi
IF %CurrWeekDayNumber% == 4 SET CurrWeekDay=Do
IF %CurrWeekDayNumber% == 5 SET CurrWeekDay=Fr
IF %CurrWeekDayNumber% == 6 SET CurrWeekDay=Sa
IF %CurrWeekDayNumber% == 7 SET CurrWeekDay=So

:: 52,53
SET _tmp_YN=%CurrYear%
SET /A _tmp_NR1 = 8 - _tmp_01
IF %CurrDayNumber% LEQ %_tmp_NR1% IF %_tmp_01% LEQ 4 GOTO CW1
  SET /A _tmp_YN-=1
  SET /A CurrWeekNumber=52
  IF %_tmp_01% EQU 5 SET /A CurrWeekNumber += 1
  IF %_tmp_01% EQU 6 IF DEFINED _tmp_LYisLeap SET /A CurrWeekNumber += 1

:CW1
IF %_tmp_YN% NEQ %CurrYear% GOTO WNY
  SET _tmp_I=365
  IF DEFINED _tmp_CYisLeap SET /A _tmp_I += 1
  SET /A _tmp_NR2 = _tmp_I - CurrDayNumber
  SET /A _tmp_NR3 = 4 - CurrWeekDayNumber
  IF %_tmp_NR2% GEQ %_tmp_NR3% GOTO WNY
    SET _tmp_YN=%_tmp_LY%
    SET CurrWeekNumber=1

:WNY
IF %_tmp_YN% EQU %CurrYear% GOTO Layout
  SET /A _tmp_J = CurrDayNumber - CurrWeekDayNumber + _tmp_01 + 6
  SET /A CurrWeekNumber = _tmp_J / 7
  IF %_tmp_01% GTR 4 SET /A CurrWeekNumber -= 1

:: Week numbers are 2 digits wide in ISO 8601
:Layout
IF %CurrWeekNumber% LEQ 9 SET CurrWeekNumber=0%CurrWeekNumber%

:: Output
IF /i "%~3" == "/print" (SET Curr%~4) ELSE IF /i "%~2" == "/print" SET Curr%~3

:Cleanup
SET _tmp_position=
SET _tmp_F=
SET _tmp_Given=
SET _tmp_P=
SET _tmp_com=
SET _tmp_f2=
SET _tmp_YY=
SET _tmp_C=
SET _tmp_G=
SET _tmp_LY=
SET _tmp_4=
SET _tmp_100=
SET _tmp_400=
SET _tmp_CYisLeap=
SET _tmp_LYisLeap=
SET _tmp_01=
SET _tmp_NR1=
SET _tmp_NR2=
SET _tmp_NR3=
SET _tmp_YN=
SET _tmp_I=
SET _tmp_J=

nach oben


Literatur & Dank

Mein Dank geht an die Leute, die die folgenden, hervorragenden Websites machen:
http://66.39.60.58/y2k.html - viele nützliche Links zum Datum
http://zijlema.basicguru.com/weeknbr.html - Berechnung in Basic
http://www.phys.uu.nl/~vgent/calendar/isocalendar.htm - Gute Infos zum ISO Kalendar
http://utopia.knoware.nl/~ocorten/timex/wkcalc.htm - Generelle Berechnung der Wochennummer
http://www.personal.ecu.edu/mccartyr/ISOwdALG.txt - Berechnung der Wochennummer
http://www.fpschultze.de/batstuff.html - Batch Scripting DELUXE
http://www.robvanderwoude.com/index.html - Batch Scripting

nach oben


Excel-Lösung

Die Wochennummer in Excel, vielen Dank an Thomas WEBER aus Österreich, der auch gerne Fragen zum Einbinden beantwortet, Ihr erreicht ihn über mich.

Public Function CALWEEK(DayX As Date)
Dim dteTemp As Date, Weeks As Integer
  
  dteTemp = DateSerial(Year(DayX), 1, 1)        '1. Jänner
  'Kalenderwoche des 1. Jänner bestimmen
  Select Case WeekDay(dteTemp, vbMonday)        'Wochentag 1. Jänner
  Case 1 To 4                                   'Mo - Do
    CALWEEK = 1
  Case 5                                        'Fr
    CALWEEK = 53
  Case 6                                        'Sa
    'Wenn das Vorjahr ein Schaltjahr war: 53, sonst: 52
    CALWEEK = dteTemp - DateSerial(Year(dteTemp - 1), 1, 1) - 313
  Case 7                                        'So
    CALWEEK = 52
  End Select
  
  'letzter Montag vor dem 2. Jänner
  dteTemp = dteTemp + 1 - WeekDay(dteTemp, vbMonday)
  'ganze Wochen seit letztem Montag vor dem 2. Jänner
  Weeks = (DayX - dteTemp) \ 7
    If CALWEEK = 1 Then                                 'Woche diese Jahres
    CALWEEK = Format(1 + Weeks, "00") & " / " & Right(Year(DayX), 2)
  ElseIf Weeks = 0 Then                                 'letzte Woche vom Vorj.
    CALWEEK = Format(CALWEEK, "00") & " / " & Right(Year(dteTemp), 2)
  Else                                                  'Woche diese Jahres
    CALWEEK = Format(Weeks, "00") & " / " & Right(Year(DayX), 2)
  End If
  
  dteTemp = DateSerial(Year(DayX), 12, 31)              '31.Dezember
  'Wenn der Do der Woche des DayX im nächsten Jahr liegt
  If DayX + 4 - WeekDay(DayX, vbMonday) > dteTemp Then
    'erste Woche vom nächsten Jahr
    CALWEEK = Format(1, "00") & " / " & Right(Year(dteTemp + 1), 2)
  End If 
End Function 

nach oben


Diese Seite ist Teil von robertkehl.de


Glossar

Log-Files - Dateien, in denen Programme ihre Ausgaben speichern
pures Windows - Windows ohne zusätzlich installierte Software wie Office, Perl, etc.
Einzeiler - das hier: SET CurrDay = %DATE:~3,2% & ECHO Datum gespeichert in CurrDay
Mars - ein Schokoriegel
kiki - extrem leicht, super einfach, vernachlässigbar, nicht der Rede wert, für Laien, 5. Klasse
easy - siehe kiki
MOD - Bestimmt den Rest einer Division: 25 MOD 4 = 1, weil INT(25/4) * 4 = 24 = 25 - 1
%PATH% - Umgebungsvariable, die die Verzeichnisse beinhaltet, die bei der Eingabe eines Befehls dursucht werden: ECHO %PATH%
%WINDIR% - Umgebungsvariable, die das Windows-Verzeichnis beinhaltet, z.B. C:\WINNT

nach oben

(letzte Änderung: 26.06.2004 )