Il y a très souvent des questions relatives à la date / heure relative à résoudre avec le fichier batch. Mais l'interpréteur de ligne de commande cmd.exe n'a aucune fonction pour les calculs de date / heure. De nombreuses bonnes solutions de travail utilisant des applications ou des scripts de console supplémentaires ont déjà été publiées ici, sur d'autres pages de Stack Overflow et sur d'autres sites Web.
Pour les opérations basées sur la date / l'heure, il est courant de convertir une chaîne de date / heure en secondes depuis un jour déterminé. Très courant est 1970-01-01 00:00:00 UTC. Mais tout jour ultérieur pourrait également être utilisé en fonction de la plage de dates requise pour prendre en charge une tâche spécifique.
Jay a publié 7daysclean.cmd contenant une solution rapide de "date en secondes" pour l'interpréteur de ligne de commande cmd.exe . Mais il ne prend pas en compte correctement les années bissextiles. JR a publié un module complémentaire pour prendre en compte le jour bissextile de l'année en cours, mais en ignorant les autres années bissextiles depuis l'année de base, c'est-à-dire depuis 1970.
J'utilise depuis 20 ans des tables statiques (tableaux) créées une fois avec une petite fonction C pour obtenir rapidement le nombre de jours y compris les jours intercalaires du 01/01/1970 dans les fonctions de conversion date / heure dans mes applications écrites en C / C ++.
Cette méthode de table très rapide peut également être utilisée dans le code batch à l'aide de la commande FOR . J'ai donc décidé de coder le sous-programme batch GetSeconds
qui calcule le nombre de secondes depuis 1970-01-01 00:00:00 UTC pour une chaîne de date / heure passée à cette routine.
Remarque: les secondes intercalaires ne sont pas prises en compte car les systèmes de fichiers Windows ne prennent pas non plus en charge les secondes intercalaires.
Tout d'abord, les tableaux:
Jours depuis 1970-01-01 00:00:00 UTC pour chaque année, y compris les jours bissextiles.
1970 - 1979: 0 365 730 1096 1461 1826 2191 2557 2922 3287
1980 - 1989: 3652 4018 4383 4748 5113 5479 5844 6209 6574 6940
1990 - 1999: 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592
2000 - 2009: 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245
2010 - 2019: 14610 14975 15340 15706 16071 16436 16801 17167 17532 17897
2020 - 2029: 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550
2030 - 2039: 21915 22280 22645 23011 23376 23741 24106 24472 24837 25202
2040 - 2049: 25567 25933 26298 26663 27028 27394 27759 28124 28489 28855
2050 - 2059: 29220 29585 29950 30316 30681 31046 31411 31777 32142 32507
2060 - 2069: 32872 33238 33603 33968 34333 34699 35064 35429 35794 36160
2070 - 2079: 36525 36890 37255 37621 37986 38351 38716 39082 39447 39812
2080 - 2089: 40177 40543 40908 41273 41638 42004 42369 42734 43099 43465
2090 - 2099: 43830 44195 44560 44926 45291 45656 46021 46387 46752 47117
2100 - 2106: 47482 47847 48212 48577 48942 49308 49673
Le calcul des secondes pour les années 2039 à 2106 avec une époque commençant le 01/01/1970 n'est possible qu'en utilisant une variable 32 bits non signée, c'est-à-dire non signée longue (ou non signée int) en C / C ++.
Mais cmd.exe utilise pour les expressions mathématiques une variable 32 bits signée. Par conséquent, la valeur maximale est 2147483647 (0x7FFFFFFF) qui est 2038-01-19 03:14:07.
Information sur l'année bissextile (Non / Oui) pour les années 1970 à 2106.
1970 - 1989: N N Y N N N Y N N N Y N N N Y N N N Y N
1990 - 2009: N N Y N N N Y N N N Y N N N Y N N N Y N
2010 - 2029: N N Y N N N Y N N N Y N N N Y N N N Y N
2030 - 2049: N N Y N N N Y N N N Y N N N Y N N N Y N
2050 - 2069: N N Y N N N Y N N N Y N N N Y N N N Y N
2070 - 2089: N N Y N N N Y N N N Y N N N Y N N N Y N
2090 - 2106: N N Y N N N Y N N N N N N N Y N N
^ year 2100
Nombre de jours jusqu'au premier jour de chaque mois de l'année en cours.
Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
Year with 365 days: 0 31 59 90 120 151 181 212 243 273 304 334
Year with 366 days: 0 31 60 91 121 152 182 213 244 274 305 335
La conversion d'une date en nombre de secondes depuis le 01/01/1970 est assez simple en utilisant ces tableaux.
Attention, s'il vous plaît!
Le format des chaînes de date et d'heure dépend des paramètres de région et de langue de Windows. Les délimiteurs et l'ordre des jetons affectés aux variables d'environnement Day
, Month
et Year
dans la première boucle FOR de GetSeconds
doivent être adaptés au format date / heure local si nécessaire.
Il est nécessaire d'adapter la chaîne de date de la variable d'environnement si le format de date dans la variable d'environnement DATE est différent du format de date utilisé par la commande FOR on %%~tF
.
Par exemple, quand se %DATE%
développe en Sun 02/08/2015
tandis que se %%~tF
développe en 02/08/2015 07:38 PM
le code ci-dessous peut être utilisé avec la modification de la ligne 4 à:
call :GetSeconds "%DATE:~4% %TIME%"
Cela se traduit par le passage au sous-programme uniquement 02/08/2015
- la chaîne de date sans les 3 lettres de l'abréviation du jour de la semaine et le caractère espace de séparation.
Vous pouvez également utiliser ce qui suit pour passer la date actuelle au format correct:
call :GetSeconds "%DATE:~-10% %TIME%"
Maintenant, les 10 derniers caractères de la chaîne de date sont passés à la fonction GetSeconds
et, par conséquent, peu importe si la chaîne de date de la variable d'environnement DATE est avec ou sans jour de la semaine tant que le jour et le mois sont toujours avec 2 chiffres dans l'ordre attendu, c'est-à-dire au format dd/mm/yyyy
ou dd.mm.yyyy
.
Voici le code batch avec des commentaires explicatifs qui sort juste quel fichier supprimer et quel fichier conserver dans l' C:\Temp
arborescence des dossiers, voir le code de la première boucle FOR .
@echo off
setlocal EnableExtensions EnableDelayedExpansion
rem Get seconds since 1970-01-01 for current date and time.
call :GetSeconds "%DATE% %TIME%"
rem Subtract seconds for 7 days from seconds value.
set /A "LastWeek=Seconds-7*86400"
rem For each file in each subdirectory of C:\Temp get last modification date
rem (without seconds -> append second 0) and determine the number of seconds
rem since 1970-01-01 for this date/time. The file can be deleted if seconds
rem value is lower than the value calculated above.
for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
call :GetSeconds "%%~tF:0"
rem if !Seconds! LSS %LastWeek% del /F "%%~fF"
if !Seconds! LEQ %LastWeek% (
echo Delete "%%~fF"
) else (
echo Keep "%%~fF"
)
)
endlocal
goto :EOF
rem No validation is made for best performance. So make sure that date
rem and hour in string is in a format supported by the code below like
rem MM/DD/YYYY hh:mm:ss or M/D/YYYY h:m:s for English US date/time.
:GetSeconds
rem If there is " AM" or " PM" in time string because of using 12 hour
rem time format, remove those 2 strings and in case of " PM" remember
rem that 12 hours must be added to the hour depending on hour value.
set "DateTime=%~1"
set "Add12Hours=0"
if "%DateTime: AM=%" NEQ "%DateTime%" (
set "DateTime=%DateTime: AM=%"
) else if "%DateTime: PM=%" NEQ "%DateTime%" (
set "DateTime=%DateTime: PM=%"
set "Add12Hours=1"
)
rem Get year, month, day, hour, minute and second from first parameter.
for /F "tokens=1-6 delims=,-./: " %%A in ("%DateTime%") do (
rem For English US date MM/DD/YYYY or M/D/YYYY
set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
rem For German date DD.MM.YYYY or English UK date DD/MM/YYYY
rem set "Day=%%A" & set "Month=%%B" & set "Year=%%C"
set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)
rem echo Date/time is: %Year%-%Month%-%Day% %Hour%:%Minute%:%Second%
rem Remove leading zeros from the date/time values or calculation could be wrong.
if "%Month:~0,1%" EQU "0" ( if "%Month:~1%" NEQ "" set "Month=%Month:~1%" )
if "%Day:~0,1%" EQU "0" ( if "%Day:~1%" NEQ "" set "Day=%Day:~1%" )
if "%Hour:~0,1%" EQU "0" ( if "%Hour:~1%" NEQ "" set "Hour=%Hour:~1%" )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
rem Add 12 hours for time range 01:00:00 PM to 11:59:59 PM,
rem but keep the hour as is for 12:00:00 PM to 12:59:59 PM.
if "%Add12Hours%" == "1" (
if %Hour% LSS 12 set /A Hour+=12
)
set "DateTime="
set "Add12Hours="
rem Must use 2 arrays as more than 31 tokens are not supported
rem by command line interpreter cmd.exe respectively command FOR.
set /A "Index1=Year-1979"
set /A "Index2=Index1-30"
if %Index1% LEQ 30 (
rem Get number of days to year for the years 1980 to 2009.
for /F "tokens=%Index1% delims= " %%Y in ("3652 4018 4383 4748 5113 5479 5844 6209 6574 6940 7305 7670 8035 8401 8766 9131 9496 9862 10227 10592 10957 11323 11688 12053 12418 12784 13149 13514 13879 14245") do set "Days=%%Y"
for /F "tokens=%Index1% delims= " %%L in ("Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N") do set "LeapYear=%%L"
) else (
rem Get number of days to year for the years 2010 to 2038.
for /F "tokens=%Index2% delims= " %%Y in ("14610 14975 15340 15706 16071 16436 16801 17167 17532 17897 18262 18628 18993 19358 19723 20089 20454 20819 21184 21550 21915 22280 22645 23011 23376 23741 24106 24472 24837") do set "Days=%%Y"
for /F "tokens=%Index2% delims= " %%L in ("N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N N Y N N") do set "LeapYear=%%L"
)
rem Add the days to month in year.
if "%LeapYear%" == "N" (
for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)
rem Add the complete days in month of year.
set /A "Days+=Day-1"
rem Calculate the seconds which is easy now.
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"
rem Exit this subroutine
goto :EOF
Pour des performances optimales, il serait préférable de supprimer tous les commentaires, c'est-à-dire toutes les lignes commençant par rem après 0-4 espaces de tête.
Et les tableaux peuvent également être rendus plus petits, c'est-à-dire en diminuant la plage de temps de 1980-01-01 00:00:00 à 2038-01-19 03:14:07 comme actuellement pris en charge par le code de lot ci-dessus, par exemple jusqu'en 2015-01 -01 au 31/12/2019, comme le code ci-dessous l'utilise, ce qui supprime vraiment les fichiers de plus de 7 jours dans l' C:\Temp
arborescence des dossiers.
De plus, le code de lot ci-dessous est optimisé pour un format horaire de 24 heures.
@echo off
setlocal EnableDelayedExpansion
call :GetSeconds "%DATE:~-10% %TIME%"
set /A "LastWeek=Seconds-7*86400"
for /F "delims=" %%F in ('dir /A-D-H-S /B /S "C:\Temp"') do (
call :GetSeconds "%%~tF:0"
if !Seconds! LSS %LastWeek% del /F "%%~fF"
)
endlocal
goto :EOF
:GetSeconds
for /F "tokens=1-6 delims=,-./: " %%A in ("%~1") do (
set "Day=%%B" & set "Month=%%A" & set "Year=%%C"
set "Hour=%%D" & set "Minute=%%E" & set "Second=%%F"
)
if "%Month:~0,1%" EQU "0" ( if "%Month:~1%" NEQ "" set "Month=%Month:~1%" )
if "%Day:~0,1%" EQU "0" ( if "%Day:~1%" NEQ "" set "Day=%Day:~1%" )
if "%Hour:~0,1%" EQU "0" ( if "%Hour:~1%" NEQ "" set "Hour=%Hour:~1%" )
if "%Minute:~0,1%" EQU "0" ( if "%Minute:~1%" NEQ "" set "Minute=%Minute:~1%" )
if "%Second:~0,1%" EQU "0" ( if "%Second:~1%" NEQ "" set "Second=%Second:~1%" )
set /A "Index=Year-2014"
for /F "tokens=%Index% delims= " %%Y in ("16436 16801 17167 17532 17897") do set "Days=%%Y"
for /F "tokens=%Index% delims= " %%L in ("N Y N N N") do set "LeapYear=%%L"
if "%LeapYear%" == "N" (
for /F "tokens=%Month% delims= " %%M in ("0 31 59 90 120 151 181 212 243 273 304 334") do set /A "Days+=%%M"
) else (
for /F "tokens=%Month% delims= " %%M in ("0 31 60 91 121 152 182 213 244 274 305 335") do set /A "Days+=%%M"
)
set /A "Days+=Day-1"
set /A "Seconds=Days*86400+Hour*3600+Minute*60+Second"
goto :EOF
Pour encore plus d'informations sur les formats de date et d'heure et les comparaisons d'heure de fichier sous Windows, consultez ma réponse sur savoir si le fichier a plus de 4 heures dans un fichier de commandes avec de nombreuses informations supplémentaires sur les temps de fichier.