Es gibt sehr oft relative datums- / zeitbezogene Fragen, die mit einer Batchdatei gelöst werden müssen. Der Befehlszeileninterpreter cmd.exe hat jedoch keine Funktion für Datums- / Zeitberechnungen. Viele gute Arbeitslösungen mit zusätzlichen Konsolenanwendungen oder Skripten wurden bereits hier, auf anderen Seiten von Stack Overflow und auf anderen Websites veröffentlicht.
Für Operationen, die auf Datum / Uhrzeit basieren, ist die Anforderung üblich, eine Datums- / Zeitzeichenfolge seit einem bestimmten Tag in Sekunden umzuwandeln. Sehr häufig ist 1970-01-01 00:00:00 UTC. Jeder spätere Tag kann jedoch auch verwendet werden, abhängig vom Datumsbereich, der für die Unterstützung einer bestimmten Aufgabe erforderlich ist.
Jay hat 7daysclean.cmd gepostet, das eine schnelle "Datum zu Sekunden" -Lösung für den Befehlszeileninterpreter cmd.exe enthält . Aber es dauert nicht richtig Schaltjahre zu berücksichtigen. JR hat ein Add-On veröffentlicht, um den Schalttag im laufenden Jahr zu berücksichtigen, die anderen Schaltjahre seit dem Basisjahr, dh seit 1970, zu ignorieren.
Ich verwende seit 20 Jahren statische Tabellen (Arrays), die einmal mit einer kleinen C-Funktion erstellt wurden, um schnell die Anzahl der Tage einschließlich der Schalttage vom 01.01.1970 in Datums- / Zeitkonvertierungsfunktionen in meinen in C / C ++ geschriebenen Anwendungen zu ermitteln.
Diese sehr schnelle Tabellenmethode kann auch im Batch-Code mit dem Befehl FOR verwendet werden . Deshalb habe ich mich entschlossen, die Batch-Subroutine zu codieren, die GetSeconds
die Anzahl der Sekunden seit 1970-01-01 00:00:00 UTC für eine an diese Routine übergebene Datums- / Zeitzeichenfolge berechnet.
Hinweis: Schaltsekunden werden nicht berücksichtigt, da die Windows-Dateisysteme auch keine Schaltsekunden unterstützen.
Zunächst die Tabellen:
Tage seit 1970-01-01 00:00:00 UTC für jedes Jahr einschließlich Schalttagen.
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
Die Berechnung der Sekunden für die Jahre 2039 bis 2106 mit Beginn der Epoche 1970-01-01 ist nur mit einer vorzeichenlosen 32-Bit-Variablen möglich, dh einer vorzeichenlosen langen (oder vorzeichenlosen int) in C / C ++.
Aber cmd.exe Verwendung für mathematische Ausdrücke unterzeichnete einen 32-Bit - Variable. Daher ist der Maximalwert 2147483647 (0x7FFFFFFF), also 2038-01-19 03:14:07.
Schaltjahrinformation (Nein / Ja) für die Jahre 1970 bis 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
Anzahl der Tage bis zum ersten Tag eines jeden Monats im laufenden Jahr.
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
Das Konvertieren eines Datums in eine Anzahl von Sekunden seit dem 01.01.1970 ist mit diesen Tabellen recht einfach.
Aufmerksamkeit bitte!
Das Format der Datums- und Zeitzeichenfolgen hängt von der Windows-Region und den Spracheinstellungen ab. Die Trennzeichen und die Reihenfolge der Token an die Umgebungsvariablen zugewiesen Day
, Month
und Year
in erster FOR - Schleife GetSeconds
muß , wenn notwendig , um lokales Datums- / Uhrzeitformat angepasst werden.
Die Datumszeichenfolge der Umgebungsvariablen muss angepasst werden, wenn sich das Datumsformat in der Umgebungsvariablen DATE vom Datumsformat unterscheidet, das vom Befehl FOR on verwendet wird %%~tF
.
Wenn zum Beispiel %DATE%
erweitert wird, Sun 02/08/2015
während %%~tF
zu 02/08/2015 07:38 PM
dem folgenden Code erweitert wird, kann Zeile 4 geändert werden, um:
call :GetSeconds "%DATE:~4% %TIME%"
Dies führt dazu, dass nur 02/08/2015
das Unterprogramm übergeben wird - die Datumszeichenfolge ohne die 3 Buchstaben der Wochentagsabkürzung und das Trennzeichen.
Alternativ kann Folgendes verwendet werden, um das aktuelle Datum im richtigen Format zu übergeben:
call :GetSeconds "%DATE:~-10% %TIME%"
Jetzt werden die letzten 10 Zeichen aus der Datumszeichenfolge an function übergeben, GetSeconds
und daher spielt es keine Rolle, ob die Datumszeichenfolge der Umgebungsvariablen DATE mit oder ohne Wochentag ist, solange Tag und Monat immer mit 2 Ziffern in der erwarteten Reihenfolge, dh im Format dd/mm/yyyy
oder, vorliegen dd.mm.yyyy
.
Hier ist der Stapelcode mit Erläuterungen zu Kommentaren, die nur die zu löschende Datei und die im C:\Temp
Ordnerbaum zu speichernde Datei ausgeben (siehe Code der ersten FOR- Schleife).
@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
Für eine optimale Leistung ist es am besten, alle Kommentare zu entfernen, dh alle Zeilen, die mit rem nach 0-4 führenden Leerzeichen beginnen.
Die Arrays können auch kleiner gemacht werden, dh der Zeitbereich von 1980-01-01 00:00:00 bis 2038-01-19 03:14:07 wird verringert, wie dies derzeit durch den obigen Batch-Code unterstützt wird, beispielsweise bis 2015-01 -01 bis 2019-12-31, wie der folgende Code verwendet, der Dateien löscht, die älter als 7 Tage im C:\Temp
Ordnerbaum sind.
Ferner ist der folgende Stapelcode für das 24-Stunden-Zeitformat optimiert.
@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
Weitere Informationen zu Datums- und Zeitformaten und Dateizeitvergleichen unter Windows finden Sie in meiner Antwort unter Finden Sie heraus, ob die Datei in einer Batchdatei älter als 4 Stunden ist, mit vielen zusätzlichen Informationen zu den Dateizeiten.