Also, does anyone have a good batch only routine for getting the last day of
any given month? The only thing I was able to come up with was this
vbscrpt/batch hybrid solution.
[1]@echo off & setlocal enableextensions enabledelayedexpansion
[2] for /L %%j in (1,1,12) do (
[3] call :LastDayofMonthN %%j eom
[4] echo !eom!)
[5] pause
[6] call :LastDayofMonth eom
[7] echo %eom%
[8] endlocal & goto :EOF
[9] :LastDayofMonthN
[10] if not exist %temp% mkdir %temp%
[11] if "%1"=="" (set d=Month^(Date^)) else (set d=%1)
[12] echo>%temp%\tmp$$$.vbs WScript.Echo DateSerial(Year(Date),%d% + 1,0)
[13] for /f %%n in ('cscript //nologo %temp%\tmp$$$.vbs') do set eom=%%n
[14] set eom=%eom:~3,2%
[15] for %%f in (%temp%\tmp$$$.vbs) do if exist %%f del %%f
[16] set %2=%eom%
[17] goto :EOF
[18] :LastDayofMonth
[19] if not exist %temp% mkdir %temp%
[20] echo>%temp%\tmp$$$.vbs WScript.Echo DateSerial(Year(Date),Month(Date)
+ 1,0)
[21] for /f %%n in ('cscript //nologo %temp%\tmp$$$.vbs') do set eom=%%n
[22] set eom=%eom:~3,2%
[23] for %%f in (%temp%\tmp$$$.vbs) do if exist %%f del %%f
[24] set %1=%eom%
[25] goto :EOF
TIA
Matt
@echo off
setlocal
:: the format of the %date% variable must be in the following format:
:: set date=Fr 26.05.2006
:: if not, change the next two lines
set /a y=%date:~9,4%
set /a m=1%date:~6,2%-100
call :lastday
echo.
set y=2000
for /L %%j in (1,1,12) do (
set m=%%j
call :lastday)
echo.
set y=2006
for /L %%j in (1,1,12) do (
set m=%%j
call :lastday)
goto :eof
:lastday
set /a d=28+((62648012^>^>(2*%m%))^&3)+(!(%y% %% 4))*(!(%m%-2))
echo %y% %m% %d%
This works for me. You may need to adjust %date:~x,x% to work for you.
@echo off
setlocal
set month=%date:~4,2%
set eom=31
for %%? in (4 6 9 11) do if %month%==%%? set eom=30
if not %month%==2 goto done
set eom=28
set isleap=%date:~10,4%
set /a isleap=%isleap% %% 4
if %isleap%==0 set eom=29
:done
endlocal
echo eom=%eom%
--
Todd Vargo
(Post questions to group only. Remove "z" to email personal messages)
Here is my test code so far
@echo off&setlocal
set dt=05/26/2006
set /a y=%dt:~6,4%
set /a m=1%dt:~0,2%-100
call :lastday d
echo %d%
endlocal&goto :eof
:lastday
set /a d=28+((62648012^>^>(2*%m%))^&3)+(!(%y% %% 4))*(!(%m%-2))
set %1=%d%
Thanks
Matt
"Herbert Kleebauer" <kl...@unibwm.de> wrote in message
news:44770191...@unibwm.de...
You don't have to modify the code for the :lastday subroutine. All
you have to do is, to set the variables y and m with the year and
month. Only the setting of this variable depends on the local date
format. It doesn't matter whether you use 2006 or 6 for the year
(but no leading zero like 06).
> Here is my test code so far
Didn't it work?
> set /a d=28+((62648012^>^>(2*%m%))^&3)+(!(%y% %% 4))*(!(%m%-2))
The length of a month can be written as 28 + x with 0<=x<=3.
To encode a value 0..3 we need two bits. So we can put all
12 two bit values into one 32 bit value
month: 12 11 10 9 8 7 6 5 4 3 2 1
x 11 10 11 10 11 11 10 11 10 11 00 11 00 = 62648012
To get x for the given month we have to shift 62648012
to the right by 2*month and use only the last two bits
(&3) of the shifted value. If it is a leap year
( !(%y% %% 4)) is one) and it is February ( !(%m%-2) is one)
we have to add 1.
No, unfortunately. It returns 34 for the current date. I'm trying to break
it down to see where the failure is occuring. The actual formula that is
being evaluated when I run this is: 28+((62648012>>(2*5))&3)+((5-2))
Here is some new test code:
@echo off&setlocal
set dt=Any Date in mm/dd/yyyy format
set /a y=%dt:~6,4%
set /a m=1%dt:~0,2%-100
echo %m%%y%
call :lastday d
::echo %d%
endlocal&goto :eof
:lastday
echo 28+
set /a z=((62648012^>^>(2*%m%))^&3)
echo ((62648012^>^>(2*%m%))^&3) = %z%
set /a x=(!(%y% %% 4))*(!(%m%-2))
echo (!(%y% %% 4))*(!(%m%-2)) = %x%
set /a w=28+%z%+%x%
echo Equals 28+%z%+%x% = %w%
C:\WINDOWS>lastdaybatchonly
32004
28+
((62648012>>(2*3))&3) = 3
((3-2)) = 1
Equals 28+3+1 = 32
C:\WINDOWS>lastdaybatchonly
22000
28+
((62648012>>(2*2))&3) = 0
((2-2)) = 0
Equals 28+0+0 = 28
It doesn't look like it's seeing the "year mod 4" part?
Thanks for your assistance
Matt
> "Herbert Kleebauer" <kl...@unibwm.de> wrote in message
> news:44773956...@unibwm.de...
>>
>> Didn't it work?
>>
>>
>>> set /a d=28+((62648012^>^>(2*%m%))^&3)+(!(%y% %% 4))*(!(%m%-2))
>>
>
> No, unfortunately. It returns 34 for the current date.
This code, as you posted, echoes 31 for me, Win XP SP2.
@echo off&setlocal
set dt=05/26/2006
set /a y=%dt:~6,4%
set /a m=1%dt:~0,2%-100
call :lastday d
echo %d%
endlocal&goto :eof
:lastday
set /a d=28+((62648012^>^>(2*%m%))^&3)+(!(%y% %% 4))*(!(%m%-2))
set %1=%d%
> ((3-2)) = 1
Then you have enabled delayed expansion. Either disable it
(insert SETLOCAL DISABLEDELAYEDEXPANSION at the begin of your batch)
or escape the ! charcter.
Thanks Herbert. I'm going to play with this binary shifting some more..
Matt
"Herbert Kleebauer" <kl...@unibwm.de> wrote in message
news:44775A4C...@unibwm.de...
>Also, does anyone have a good batch only routine for getting the last day of
>any given month? The only thing I was able to come up with was this
>vbscrpt/batch hybrid solution.
>[9] :LastDayofMonthN
>[10] if not exist %temp% mkdir %temp%
>[11] if "%1"=="" (set d=Month^(Date^)) else (set d=%1)
>[12] echo>%temp%\tmp$$$.vbs WScript.Echo DateSerial(Year(Date),%d% + 1,0)
That's the best algorithm, for any language that has something with
parameters behaving like those of DateSerial, with over- & under- range;
but you might do better to output Day(DateSerial(...))
In Javascript you would not need the +1.
When not using such a routine, it will be desirable to specify whether
the year range for "any given month", since the mod-4 leap algorithm is
incomplete.
--
© John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v4.00 MIME. ©
Web <URL:http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc : <URL:http://www.merlyn.demon.co.uk/programs/> - see 00index.htm
Dates - miscdate.htm moredate.htm js-dates.htm pas-time.htm critdate.htm etc.
Set/? does not explain ! usage. :(
maybe Herbert will be kind enough to explain exactly what it does.
"Todd Vargo" <tlv...@sbcglobal.netz> wrote in message
news:sWOdg.98881$dW3....@newssvr21.news.prodigy.com...
Experimentation is a dying art. Try
for /L %n in (-3,1,3) do set /a x=!%n
Set /? shows ! as a unary operator, along with -, but doesn't describe
it. It's logical complement, just like in C, C++, awk, Perl, Java,
JavaScript, C#, which means it turns 0 and only 0 into 1 and any other
numeric value into 0. I guess the Microsoft folk thought it was obvious
what it does. All the other set /A operators correspond to C's integer
operators.
You can't experiment with something you don't know exists. As I mentioned,
SET/? does not mention ! (as seen in Win95cmd ported from Windows 2000). On
examination of SET/? output on an XP machine I see this MUF is identified.
Thanks for explaining unary meaning though. Much appreciated.
70) Calendar elements: What weekday is December 31, 2004?
163586 May 1 2006 ftp://garbo.uwasa.fi/pc/link/tscmd.zip
tscmd.zip Useful NT/2000/XP script tricks and tips, T.Salmi
:
Finally, how many days are there in a month?
@echo off & setlocal enableextensions
:: Build a Visual Basic Script
if not exist c:\mytemp mkdir c:\mytemp
findstr "'%skip%VBS" "%~f0" > c:\mytemp\tmp$$$.vbs
::
:: Assume a local date format dd.mm.yyyy
:: Customize, if necessary
set month_=2
set year_=2004
::
:: Run the VBS script with Microsoft Windows Script Host Version 5.6
cscript //nologo c:\mytemp\tmp$$$.vbs
call c:\mytemp\tmp$$$.cmd
echo %mmdays_% days in %month_%.%year_%
::
:: Clean up
for %%f in (c:\mytemp\tmp$$$.vbs c:\mytemp\tmp$$$.cmd) do del %%f
rmdir c:\mytemp
endlocal & goto :EOF
'
'................................................................
'The Visual Basic Script
'
Const ForReading = 1, ForWriting = 2, ForAppending = 8 'VBS
Dim MyDate, mm, yyyy, DaysInMonth, fout, FSO 'VBS
'
Set WshShell = WScript.CreateObject("WScript.shell") 'VBS
mm=WshShell.ExpandEnvironmentStrings("%month_%") 'VBS
yyyy=WshShell.ExpandEnvironmentStrings("%year_%") 'VBS
'
For i = 28 to 32 'VBS
Mydate = CStr(i) & "." & CStr(mm) & "." & CStr(yyyy) 'VBS
If (IsDate(MyDate)) Then 'VBS
DaysInMonth = i 'VBS
End If 'VBS
Next 'VBS
'
Set FSO = CreateObject("Scripting.FileSystemObject") 'VBS
Set fout = FSO.OpenTextFile("c:\mytemp\tmp$$$.cmd", ForWriting,
true) 'VBS
fout.WriteLine "@set mmdays_=" & DaysInMonth 'VBS
fout.Close 'VBS
The output will be
D:\TEST>cmdfaq
29 days in 2.2004
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Digital photos collection at http://www.uwasa.fi/ktt/lasktoim/photo/
DaysInMonth = Day(DateSerial(yyyy, mm+1, 0)) ' VBS seems simpler
> DaysInMonth = Day(DateSerial(yyyy, mm+1, 0)) ' VBS seems simpler
Thanks John. Note incorporated.
All the best, Timo
--
Prof. Timo Salmi ftp & http://garbo.uwasa.fi/ archives 193.166.120.5
Department of Accounting and Business Finance ; University of Vaasa
mailto:t...@uwasa.fi <http://www.uwasa.fi/~ts/> ; FIN-65101, Finland
Useful script files and tricks ftp://garbo.uwasa.fi/pc/link/tscmd.zip