1.

Solve : Batch File For Complex Date Calculations?

Answer»

Hi,
I need a bit of help with a complex batch file i am TRYING to create on Windows 2000 (and hopefully it will work on XP as well...but that's an ideal, not a requirement)

Basically i have a Jscript i want to convert to a batch file to calculate the date from the last defined day of the last 7 days. I will paste the Jscript info at the end of the post for you to get a better understanding of what i am trying to do.

For eg the script will: get date of last Monday (or other days), show in format DDMMYY or YYMMDD or even MMDDYYYY (must be able to be adapted for each situation) and then use that calculation as part of a command.

I am using wget (and other programs) to download files on a daily basis that have the date as part of their file name. So i need the date of the day i specfy to be included in that command. For eg: http://www.somesite.com/files/file290606.ext

However i may need to download files dated on Monday only made available later in the week. So for eg today might be 29/06/06 (or any date up to 7 days past the file date) but i need a file from Monday which might be 260606.
* Please note I cannot calculate from "X" days ago as the day i download the files will vary.

Here is the Jscript i have been using which should help you understand what i am talking about:


Quote

function getDateOfLastWeekday(weekday){
var date=new Date() // Get current date
var difference=0 // Set the difference between the date we want and today
if(date.getDay()<weekday){ // Has the desired weekday passed?
difference=7-(weekday-date.getDay()) // Yes, figure out how many days ago that that weekday occurred.
}
else{
difference=date.getDay()-weekday // No, figure out in how many days it will occur.
}
new_date=new Date(date.getTime()-difference*86400000) // Make a new date by removing 86400000 milliseconds for each day from today's date.
new_year=new_date.getYear().toString().substring() // Get the year, convert to string and remove first two numbers
new_month=new String((new_date.getMonth()+1)) // Get the month, convert to string
if(new_month.length==1){new_month="0"+new_month} // Prepend a 0 if neccessary
new_day=new_date.getDate().toString() // Get the day, convert to string
if(new_day.length==1){new_day="0"+new_day} // Prepend a 0 if neccessary
return new_year+new_month+new_day // Smack it all together in one big string and send it back to whoever asked!
}

var Shell = new ActiveXObject("WScript.Shell");
Shell.Run("http://www.somesite.com/files/file"+getDateOfLastWeekday(6)+".ext");




Thanks for you help. I know very basic batch commands but nothing of this level.

ExistanceOh yeah sorry this is the usage info on that Jscript i pasted the code for above in my first post:
Quote
// It takes an integer between 0 and 6 as an argument (above 6 is accepted but might give incorrect results).
// 0 is Sunday, 1 is Monday, ..., and 6 is Saturday.
// It returns the date of the previous weekday that matches the argument in the form of ddmmyy.

// So you could do:
// Shell.Run("mms://somewebsite/"+getDateOfLastWeekday(3)+".wmv");

Existanceyou can just run the javascript using cscript/wscript..no need to convert to batch...Thanks for your suggestion ghostdog74...i'm glad that someone replied.
I currently run the jscript by itself but i would much prefer to make into a standalone batch file.

The main reason is that jscript seems to run straight through its commands without waiting for any process or command to finish first, unlike a batch file where you can make it wait properly and then proceed or retry depending upon the outcome.

Does anyone know how to call the date in "any" of the ways i need to call it? Even a nudge in the right direction is better than nothing...

Thanks in advance,

ExistanceI don't even think that the ancient LANGUAGE of BATCH is designed to do domething that complex. I'm thinking of a few ideas, but it wouldn't be able to do cross-month calculations and there's no way it could know which month has 30, 31 days, etc.. It'd just be foolin around with the "ECHO %date%" command.

Wait just a minute... it might work...here's my line of thinking... maybe it CAN be done... I'm going to try an example that sets back a week from the current date...

This would require a lot of calculating, and knowledge of the number of days in a month; there's no algorithm in BATCH (*censored*, that's the second time I accidentally typed "BATVH"...) to do that. So... here I go on this...

The output of "ECHO %date%" sans the quote marks is similar to the following:

Wed 07/05/2006

Dredging up my DOS tutorial, you can take only part of that with the "~" command and save it as a variable. Remembering that the "W" is character 0 on the line, you could set x as the day with the following:

SET /A x=%date:~7,2%

That would start at character 7 and end 2 characters later. Then, x would be the number 05. Then, you could do this:

SET /A day=%x% - 7

NOTE: This only works on later operating systems. Test the /A switch by typing at a command prompt (minus the quotes): "SET /A x=7 - 2" and pressing [Enter]. If you get an error, my method won't work. If you see the number "2" then another prompt, it works and so will my method... I think.

to go back a week. This can cause negative numbers, but you can use that to your advantage. Use this to get the month:

IF %day% LEQ 0 SET /A month=%date:~4,2% - 1
IF %day% GEQ 1 SET /A month=%date:~4,2%

This says: "If the value of variable "day" is less than or equal to 0, set month as two numbers starting at the 4th character in the date minus 1. If this value is equal to or greater than 1, just take the two characters with no subtraction."

Then go through the process of doing this (I'm abbreviating the excruciating list):

IF "%month%"=="0" SET month=Dec
IF "%month%"=="01" SET month=Jan
IF "%month%"=="02" SET month=Feb
IF "%month%"=="03" SET month=Mar
IF "%month%"=="04" SET month=Apr

...

IF "%month%"=="12" SET month=Dec

Yeah, you get to do all 13. This sets up your month. But what about the negative day (if you have it)? Well, this is where I'm trying to work this out. It seems possible up to this point, but I'm getting odd errors from DOS testing this part of the code. I'll need to get back to you on this... unless you say "never mind".

This is so big, it may be my biggest challenge yet.

EDTED: I think I got it, but it will require a lot more work. Let me keep going on this, I'll keep you posted! Except that I need to run out to Wal-Mart in about half an hour, so you may need to wait for the rest of this.OK. Now you'll need to use precisely the code below. It will direct the batch file to go to the subroutine that corresponds with the month:

Code: [Select]GOTO %month%

:Jan
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:Feb
IF "%day%"=="0" set day=28
IF "%day%"=="-1" set day=27
IF "%day%"=="-2" set day=26
IF "%day%"=="-3" set day=25
IF "%day%"=="-4" set day=24
IF "%day%"=="-5" set day=23
IF "%day%"=="-6" set day=22
GOTO AfterDayChange

:Mar
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:Apr
IF "%day%"=="0" set day=30
IF "%day%"=="-1" set day=29
IF "%day%"=="-2" set day=28
IF "%day%"=="-3" set day=27
IF "%day%"=="-4" set day=26
IF "%day%"=="-5" set day=25
IF "%day%"=="-6" set day=24
GOTO AfterDayChange

:May
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:Jun
IF "%day%"=="0" set day=30
IF "%day%"=="-1" set day=29
IF "%day%"=="-2" set day=28
IF "%day%"=="-3" set day=27
IF "%day%"=="-4" set day=26
IF "%day%"=="-5" set day=25
IF "%day%"=="-6" set day=24
GOTO AfterDayChange

:Jul
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:Aug
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:Sep
IF "%day%"=="0" set day=30
IF "%day%"=="-1" set day=29
IF "%day%"=="-2" set day=28
IF "%day%"=="-3" set day=27
IF "%day%"=="-4" set day=26
IF "%day%"=="-5" set day=25
IF "%day%"=="-6" set day=24
GOTO AfterDayChange

:Oct
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:Nov
IF "%day%"=="0" set day=30
IF "%day%"=="-1" set day=29
IF "%day%"=="-2" set day=28
IF "%day%"=="-3" set day=27
IF "%day%"=="-4" set day=26
IF "%day%"=="-5" set day=25
IF "%day%"=="-6" set day=24
GOTO AfterDayChange

:Dec
IF "%day%"=="0" set day=31
IF "%day%"=="-1" set day=30
IF "%day%"=="-2" set day=29
IF "%day%"=="-3" set day=28
IF "%day%"=="-4" set day=27
IF "%day%"=="-5" set day=26
IF "%day%"=="-6" set day=25
GOTO AfterDayChange

:AfterDayChange
Two things should be noted: One. This doesn't account for the LEAP year. My response: Shut up. I really don't care at this point.

The other is that it was intentional that Jul and Aug have 31 days. This is a blinding flash of the obvious, but I've had people argue that that is impossible.

Now, we have the month and day of a week ago. The year is easily gotten:

SET year=%date:~10%

Finally, at the bottom, you can do this:

ECHO A week ago, it was day %day% of %month%, %year%.

One final note: I haven't figured out a way to make this work cross-years. Just don't run it between January 1 and January 7 and you'll be fine.

EDIT AGAIN: Hold on, I'm not getting a good month result. Let me debug this... ...got it. Piece of cake.Turns out, I made a human error: I forgot to fill in the other months! *smacks forehead*

Attached is a zipped version of the completed sample you just read. Extract to C:\, then go to the command prompt, type "cd \" bar the quotes, then type "one_week_ago" minus the quotes to see the results of my work. Open the batch file in Notepad to view the source.

It isn't exactly what you asked for, but it does show how it is possible (although hard) to do something like this. *pats self on back*

EDIT AGAIN: Hold it, another fatal error noticed. Give me a minute...

EDIT ONE LAST TIME: Fixed.Thanks for all the work you have done Dilbert. It's much appreciated.

I tested the script and it came back with :A week ago, it was day 31 of May, 2006."
I'm in Australia so the date today is Thursday 06/07/2006.

I think a little reworking of the batch file would FIX that though. But at least now i can see how it is done.

I wasn't aware it was so hard to get a batch file to do what i wanted. What is even harder is that i had hoped to display the date not in terms of from "X" days ago but from say the last "Tuesday" or "Monday" (or other days) from within the last week, displayed in the format DDMMYY (or others) and used within a command to get a file like: http://www/somesite.com/file"date_of_last_past_Monday".wmv etc.

I'm thinking i might have been a little unrealistic to expect to achieve this with just a batch file. The work that would be involved just to do that (including with leap years) is just unbelievable.

I would assume you would have to calculate the date say from 1-6 days ago individually, then associate that with the day name (like Monday, Tuesday etc) which fell on that date, then figure out a way to get the format i need (DDMMYY or MMDDYY or DDMMYYYY etc).....WOW. Erm....

What do you think? Am i expecting too much to be able to achieve all this from a humble little batch file?

ExistanceQuote
Thanks for all the work you have done Dilbert. It's much appreciated.

I tested the script and it came back with :A week ago, it was day 31 of May, 2006."
I'm in Australia so the date today is Thursday 06/07/2006.

Does May not have 31 days? Or is it different in Australia? I'm in the USA so I have no idea. But, in the USA, on the 7th of any day, going back 7 days would bring the day counter to "0", so it would roll back to the previous month, or June. June has 30 days, so a day value of "0" would be reset to the last June day possible, or "June 30".

By my calender, it is the 5th of July, and the result on my PC is the following:

Quote
A week ago, it was day 28 of Jun, 2006.

According to the standard USA calendar, this would be a correct answer and the file is functioning as intended.

Again, if our calenders are different (Like I said, it's 7/5/2006 here, though it'll be 7/6/2006 in 2 hours), that would explain it. IF they're not different, something went wrong somewhere between finishing debugging and the final upload. And not much happened between those two points in time.

BATCH is extremely limited; it's an antique method of "programming". If I knew how, I'd use scripts for everything instead of BATCH. But I'll need to learn the stuff, then I'll have to get Norton to accept my VBS files, etc... it's a project for later.

I'm not 100% sure I understand what you want. Just so I don't run off making a seemingly impossible batch file you don't need (that was 4 KB -- pretty large for a BATCH), Let me see if I get what you're saying:

1. User inputs a day of the week, such as "Tuesday".
2. Display all files in the current directory that were made this week, from that date to today.
3. Do something with these files.

If that's what you're looking for, the job will be considerably easier than you'd think. It would be a simple matter of a few commands interpereted the correct way, then a simple DIR based on those parameters will be simple enough to show it, then any commands after that are coder's discretion.


The reason that the batch file you just saw was so darn complicated is evidence that BATCH is very limited: DOS has no real way of sobtracting dates. It isn't intelligent in that way. It just remembers the date in that format, and refreshes it every 24 hours. The BATCH file I wrote isn't as complicated as those files can get; the main reason it's so large is because it needs to send an innocent number through the wringer, as my code interperets that number to get the month and day of 7 days ago -- no small feat in DOS.if your only concern is
Quote
"jscript seems to run straight through its commands without waiting for any process or command to finish first"
i am sure jscript has some timer functions to stop for a period of time before processing continues right? why not use that...?


Discussion

No Comment Found