I was wondering if it's possible to compare a specific date (in the MM/DD/YY format) to the current system date, and get the difference in minutes?
In my past questions, I've been able to grab the dates of processes and folders and create the conversion to minutes, but I'm stumped.
My project uses Batch/CMD and Powershell, so any of those formats would be more than acceptable.
Here's the code that I use for grabbing dates to minutes with processes:
if exist "C:\Windows\Prefetch\JAVAW*.*" (
for /f "usebackq" %%A in (`
powershell -NoP -C "[int]([datetime]::Now - (gci 'C:\Windows\Prefetch\JAVAW*.*' -Force).LastWriteTime).TotalMinutes"
`) do set "AgeMinutes=%%A"
)
if exist "C:\Windows\Prefetch\JAVAW*.*" echo JAVAW.pf was modified %AgeMinutes% minutes ago.
if not exist "C:\Windows\Prefetch\JAVAW*.*" echo Error: file not found.
Is a comparison to the current date (and outputting it into minutes) possible?
Related
I have created a scheduled task in Windows that consists of running a batch script.
The problem is that this task has to be scheduled every 1st day of the month except for weekends.
For example, for the month of May, this task should run on May 02nd.
As I can't do it via the task scheduler, my idea is to schedule the execution task every day and add a condition checking that the execution day is the 1st day of the month excluding weekends.
This script would be of the following form :
if today = firstday
C:/MyExec/popo.exe arg1 arg2
Can you help me to write this script please?
Thank you in advance.
There are loads of standard methods already created for this, so just for me to experiment a bit, here is an untested method (untested meaning I simply ensured there are no syntax errors, but I have not tested all dates scenarios etc:
#echo off
if not exist _mlock break>_mlock
for /f "tokens=1-3*delims=_" %%i in ('PowerShell -Command "& {Get-Date -format "dd_ddd_MM"}"') do (
if %%i lss 5 if /i not "%%j" == "Sat" if /i not "%%j" == "Sun" findstr "m%%k">nul _mlock || (
echo m%%k>"_mlock"
start "" "C:\MyExec\popo.exe" "arg1" "arg2"
)
)
The concept: Use powershell to get a non-locale dependent dd ddd mm (04 Wed 05). I check for the day number, if it is less than 5 (overkill in this scenario) and if the ddd is not Sat or Sun and if the month's lock file does not contain the current month number, it will launch the command. If however the lock file contains the month, it will skip it until the month is updated in the file.
You're welcome to test this, if you are not happy with the temp holding file method, you can also let it add the month as a lock to the batch-file itself instead.
Notes:
This does not cater for public holidays, only weekends as per your request.
The ddd day result is language dependent and will require you to amend Sat and Sun accordingly on non English Operating systems.
This version is language-independent, excepted for optional display, and doesn't require lock files.
I've put comments inside the batch itself, feel free to ask for precisions if needed. I've tested it for March and May 2022, it works and doesn't trigger the command more than one time per month.
#echo off
setlocal enableextensions enabledelayedexpansion
REM Get current date. Powershell is used to get values in a fixed order.
for /f "usebackq tokens=1-3 delims=/" %%A in (`PowerShell -Command "& {Get-Date -format "dd/MM/yyyy"}"`) do (
set DD=%%A
set MM=%%B
set YY=%%C
REM Scheduled day.
set EDD=01
)
REM Not during first 3 days after scheduled day? Skip.
set /A maxday=!EDD!+2
if !DD! LEQ !maxday! (
if !DD! GEQ !EDD! (
goto :can_test
)
)
echo !DD!/!MM!/!YY!: Not first days after scheduled day, no need to test.
goto :eof
:can_test
REM Compute day of week: 0=Monday, ... 5=Saturday, 6=Sunday.
set /A c=(14-!MM!)/12
set /A y=!YY!-!c!
set /A m=!MM!+(12*!c!)-2
set /A d=((!EDD!-1+!y!+(!y!/4)-(!y!/100)+(!y!/400)+((31*!m!)/12))) %% 7
REM Get human-readable day. Change according to your own language, if needed. Keep order, of course.
set DAYS=Monday Tuesday Wednesday Thursday Friday Saturday Sunday
set /A i=0
for %%A in (!DAYS!) do (
set DAY=%%A
if !i! EQU !d! goto :found_day
set /A i+=1
)
:found_day
echo Day of week for !EDD!/!MM!/!YY!: !d! ^(!DAY!^)
REM If EDD is during week-end, increase expected day (2 days for Saturday, 1 day for Sunday)..
if !d! GEQ 6 (
set /A EDD+=7-!d!
REM Handle non-significative zero.
if !EDD! LSS 10 (
set EDD=0!EDD!
)
echo On week-end, schedule it to !EDD!/!MM!/!YY! instead.
)
REM Are we on scheduled day EXACTLY?
if !DD! EQU !EDD! (
REM Executing command now.
echo Executing: C:\MyExec\popo.exe arg1 arg2
REM C:\MyExec\popo.exe arg1 arg2
goto :eof
)
REM We're before or after schedule, but still within the first three days in the month.
echo Unscheduled for today ^(!DD!/!MM!/!YY!^).
goto :eof
The "day of week" formula comes from here: Mathematical curiosities / Find the day of the week with a given date (in French).
I took also Gerhard's trick for obtaining a fixed date format quickly through Powershell. It could also have been done with an embedded VBS script, since this language natively have the Weekday function, but it may have been quite unreadable to add a temporary script generation within the batch itself.
Sorry for this answer but I've no reputation to add a comment below the answer I'm referring to, the one by Wisblade:
https://stackoverflow.com/a/72113645/16641207
And I think it is important to make some additions to his beautiful answer.
I'm answering just to point out that in the wonderful piece of batch posted by Wisblade, to avoid sundays and saturdays too, at line 38 instead of this:
if !d! GEQ 6 (
there should be:
if !d! GEQ 5 (
because numbering in the "array" begins with zero.
I would also underline that this conditional expression should be changed if weekend days are different in the country where the code is used: e.g. in Israel one should check if !d! is NOT 0 and NOT 6 (not a monday nor a sunday, but saturdays are workdays there, too).
Apart from that, I gave a big +1 to his question, works so beautifully.
I used in a scheduled task, combined with the ability of Windows Scheduled Tasks to be scheduled only on first mon/tue/wed/thu/fri of every month, and doing this I'm able to execute my instruction just on first working day of every month.
Simple and effective.
This is what i would like to do:
Get Current Date, which is easy --- %DATE%
DO Current Date - 1, which i cant seem to get as i have tried different options.
I would like to get last 4 dates from the current date and then store them in 4 different variables. Then Convert each of these date into YYYYMMDD format.
So %DATE% gives me 06/04/2016.....
%DATE%
-1 should give me 05/04/2016 stored in Variable say Date1........
-2 should give me 04/04/2016 stored in Variable say Date2........
-3 should give me 03/04/2016 stored in Variable say Date3........
-4 should give me 02/04/2016 stored in Variable say Date4........
then i would like to convert value stored in each of these variables into YYYYMMDD
For ex:
05/04/2016 to 20160405 ....
04/04/2016 to 20160404 ....
03/04/2016 to 20160403 ....
02/04/2016 to 20160402 ....
with a little help from powershell:
#echo off
for /l %%d in (0,1,4) do (
for /f "tokens=*" %%i in ('powershell get-date -date $(get-date^).adddays(-%%d^) -format yyyyMMdd') do set _Date%%d=%%i
)
set _date
Explanation (copied word by word from TessellatingHeckler's comment - couldn't formulate it better):
for /L is a batch file loop which counts numbers, 1 2 3 4, and each
time through it calls PowerShell script engine with a for /f command
which is a bit of a batch file workaround. The PowerShell command gets
the current date, adds -X days to it, then gets the resulting date,
and formats it in the way you want and returns it to the batch file,
which gets one line of text back, and uses that in the do section to
set the environment variable. tokens=* tells the loop not to split the
line of text up, and the ^ are to escape special characters in batch
files
for /l works like this: for /l %%i in (<start>, <step>, <end>). In other languages it would read something like FOR i=<start> TO <end> STEP <step>
The powershell command assembles like this:
get-date - get today's date.
get-date -date <some date> get the date of <some date> (seems absurd, but in fact means "take the string <some date> and convert it to a valid date").
Now replace <some date> with $(get-date).adddays(x) - which means "take today, and add x days"
last step is formatting the resulting date to the desired format with -format <formatstring>
you can read powershell's help from cmd with powershell get-help get-date or more detailed: powershell Get-Help Get-Date -Online
I have a script that needs to connect to an ftp server and download a file that is only created on Sunday and Sunday's yyyy-mm-dd-hh-mm-ss is appended to the file name. I need to find the last Sunday's date (based on today's date, I assume) and convert it to yyyy-mm-dd (I don't care about the time) so I can construct the filename in my ftp script. I have searched a lot of threads on this and other sites, but I'm kind of a novice at batch syntax. I cannot make assumptions about the date format on the machine that will run this script, but it will be in the same timezone as the ftp server and it will be running at least Windows 7. I thought about using the PowerShell solution in HOW to find last SUNDAY DATE through batch but I've read there are issues with PS script portability. Any help is greatly appreciated. Let me know if I need to provide more detail. Thanks!
(Get-Date).AddDays(-(get-date).dayofWeek.value__)
A couple years ago I wrote a batch script to find yesterday's date. I made it able to calculate 'yesterday' based on today's date. It takes into account months ending on the 30th or 31st, and even the next few leap years. The way I wrote it expects the date to be in the format 'Wed 02/24/2016' or 'ddd MM/DD/YYYY', so it may not be useful to you.
As I look at it now, it's probably more complicated than it needs to be and could probably use some cleanup, but it worked for my purposes. You might be able to modify it somehow to make it find last Sunday, instead of yesterday.
set yearCounter=0
set yyyy=%date:~10,4%
set mm=%date:~4,2%
set dd=%date:~7,2%
::use these to override the actual date values for testing
::set yyyy=xxxx
::set mm=xx
::set dd=xx
if %dd%==01 goto LDoM ::Last Day of Month
set DS=%yyyy%%mm%%dd%
set /A yesterday=%DS%-1
goto endyesterday
:LDoM
set /A lastyyyy=%yyyy%-%yearCounter%
if %yesterday:~4,2%==01 set lastmm=12& set lastdd=31& goto LDoY ::Last Day of Year
if %yesterday:~4,2%==02 set lastmm=01& set lastdd=31
if %yesterday:~4,2%==03 set lastmm=02& goto february
if %yesterday:~4,2%==04 set lastmm=03& set lastdd=31
if %yesterday:~4,2%==05 set lastmm=04& set lastdd=30
if %yesterday:~4,2%==06 set lastmm=05& set lastdd=31
if %yesterday:~4,2%==07 set lastmm=06& set lastdd=30
if %yesterday:~4,2%==08 set lastmm=07& set lastdd=31
if %yesterday:~4,2%==09 set lastmm=08& set lastdd=31
if %yesterday:~4,2%==10 set lastmm=09& set lastdd=30
if %yesterday:~4,2%==11 set lastmm=10& set lastdd=31
if %yesterday:~4,2%==12 set lastmm=11& set lastdd=30
set yesterday=%lastyyyy%%lastmm%%lastdd%
goto endYesterday
:february
set leapyear=n
set lastdd=28
if %yesterday:~0,4%==2016 set leapyear=y
if %yesterday:~0,4%==2020 set leapyear=y
if %yesterday:~0,4%==2024 set leapyear=y
if %yesterday:~0,4%==2028 set leapyear=y
if %leapyear%==y set lastdd=29
set yesterday=%lastyyyy%%lastmm%%lastdd%
goto endYesterday
:LDoY
set /A yearCounter=%yearCounter%+1
set /A lastyyyy=%yyyy%-%yearCounter%
set yesterday=%lastyyyy%%lastmm%%lastdd%
:endYesterday
#echo off
echo %yyyy% %lastyyyy%
echo %mm% %lastmm%
echo %dd% %lastdd%
echo.
echo today = %yyyy%%mm%%dd%
echo yesterday = %yesterday%
Working with date and time using pure batch can be done, but it is not very convenient.
The GetTimestamp.bat utility makes date/time computations and formatting simple within a batch context. It is pure script (hybrid JScript/batch) that runs natively on any Windows machine from XP onward. The previous link points to the most recent version. The utility was first introduced with a number of examples at http://www.dostips.com/forum/viewtopic.php?t=4847.
Full documentation is available from the command line via getTimestamp /?, or getTimestamp /?? for paged output.
With GetTimestamp, the solution can be as simple as:
#echo off
:: Get the current day of the week, with 0=Sunday, 6=Saturday
:: to be used as an offset from today to get the most recent Sunday
call getTimeStamp -f {w} -r offset
:: Use the offset to get the most recent Sunday in YYYY-MM-DD format
call getTimeStamp -od -%offset% -f {iso-dt} -r lastSunday
:: Show the result
echo lastSunday=%lastSunday%
Try the following from a batch file:
for /f "usebackq" %%d in (`powershell -noprofile -command "'{0:yyyy-MM-dd}' -f [DateTime]::Now.AddDays(-1 * [DateTime]::Now.DayOfWeek)"`) do set "lastSunday=%%d"
echo %lastSunday%
:: -> e.g., "2016-02-21", when run on 2016-02-25
To try this directly on the command prompt, replace %%d with %d.
The PowerShell expression at the heart of the command,
[DateTime]::Now.AddDays(-1 * [DateTime]::Now.DayOfWeek),
which calculates the date of the most recent Sunday, was gratefully borrowed from the answer that you link to in your question.
'{0:yyyy-MM-dd}' -f ... applies the desired yyyy-mm-dd formatting to the date.
powershell -noprofile command ... invokes the PowerShell expression and outputs its result to stdout.
for /f "usebackq" %%d in (`...`) do set lastSunday=%%d captures the output from the PowerShell command and assigns it to batch variable lastSunday.
While invoking PowerShell for just one command from a batch file will be slow, being able to calculate the desired date so conveniently probably outweighs performance concerns.
I know there are similar questions but I have not been able to make any work. I need to check a particular file date and time against the current date and time.
So far I have
Set cdate=%date%
Set filename="c:\myfile"
If Not Exist %filename% GOTO CREATEFILE
For %%f In(%filename%) DoSet filedatetime=%%~tf
If %filedatetime:~0,-9%" == "%cdate% GOTO SHOFILE
My problem is that the cdate returned has the day of the week included in the date but the file date does not. Example cdate= Thur 1/01/2015. How can I get the cdate not to have the day of the week?
Thanks
For %%f In (%filename%) Do Set "filedatetime=%%~tf"
If "%filedatetime:~0,-9%"=="%cdate:~4%" GOTO SHOFILE
Note the required space after in and do
The set "var=value" syntax ensures that any trailing spaces on the batch line are not included in the value assigned to var.
if /i "%var%"=="value" performs a comparison on variables/values containing separators (eg spaces) The '/i' make the comparison case-insensitive if required.
Your cdate can be set like this:
SET cdate=%date:~4%
This has the following output:
echo %cdate%
01/01/2015
Each night I need to do work on a folder 36 days old from the current date. I have a system that writes files to a daily structure like below. I need to keep 35days worth on the local disk and so each night I need to archive off the 36th day. Here is the kicker... There are approx 2 million files per day, so I cannot efficiently scan the whole 2009 folder and only move files older than 35 days. What I need to do is though a batch script determine the path of the folder that is 36days old and then apply my archive logic. I have scripts to determine but having trouble doing the determination to 36 days old. In a pinch I can use perl if there is not a batch way to do this. --Shawn
Folder structure is like this:
2009\07\01
2009\07\02
2009\07\03
.
.
.
2009\08\01
2009\08\02
2009\08\03
#EDIT: Helen's great answer has me 99% of the way there. My only problem is that the month and day out of the vbs is not padded with a zero which i have to deal with in the folder structure. Does anyone have an easy way to pad in a leading 0 if the day or month is less than 10?
Here is what I am doing so far:
for /F "tokens=1-3 delims=/" %%x in ('cscript //nologo get36thday.vbs') do (
SET YYYY=%%z
SET MM=%%x
SET DD=%%y)
except %MM% ends up being 7 instead of 07
The batch option is pretty wicked you will need to calculate which month it is then based of of that run a while loop counting down the days. I would high recommend perl as it would be a few lines of code
using the DateTime module from CPAN
http://search.cpan.org/dist/DateTime/lib/DateTime.pm
my $dt = DateTime->now->subtract(days => 36);
The batch way to determine the date would be too compilcated; it's much easier to use a script for that. Sorry, no Perl sample but a VBScript one:
WScript.Echo DateAdd("d", Date, -36)
You can call this script from a batch file and read the calculated date like this:
for /f %%d in ('cscript //nologo datediff.vbs') do set dt=%%d
If you came here with google like me:
To fix the leading zero's in the .vbs I add a zero in front and strip the right 2 characters.
"0" & "7" -> "07" and "0" & "14" -> "14"
OldDateCode.vbs:
OldDate = DateAdd("d", Date, -36)
DateCode = Year(OldDate) & Right("0" & Month(OldDate), 2) & Right("0" & Day(OldDate), 2)
WScript.Echo DateCode
I also wanted to keep the 1st folder of the month so I compare the last 2 digits (day) with "01"
VBS code to check for 1st day:
If Right(DateCode, 2)="01" then
WScript.Echo "The 1st:" & vbCrLf & DateCode
Else
WScript.Echo "Not the 1st:" & vbCrLf & DateCode
End If
CheckDate.bat:
#Echo Off
Set Folder=D:
for /f %%d in ('cscript //nologo OldDateCode.vbs') do set OldDateCode=%%d
If "%OldDateCode:~6,7%"=="01" (
Echo "Old Backup: %OldDateCode% 1st of the month: keeping..."
) ELSE (
Echo "Old Backup: %OldDateCode% not the 1st of the month: removing..."
RD /S /Q "%Folder%\%OldDateCode%"
)
pause
Make a folder in D:\ with the datecode of 36 days ago. Play around with the -36 and the datecodes.