Sering ada pertanyaan terkait tanggal / waktu relatif untuk diselesaikan dengan file batch. Tetapi interpreter command line cmd.exe tidak memiliki fungsi untuk perhitungan tanggal / waktu. Banyak solusi yang berfungsi baik menggunakan aplikasi konsol tambahan atau skrip telah diposting di sini, di halaman lain dari Stack Overflow dan di situs web lain.
Umum untuk operasi berdasarkan tanggal / waktu adalah persyaratan untuk mengubah string tanggal / waktu menjadi detik sejak hari yang ditentukan. Sangat umum adalah 1970-01-01 00:00:00 UTC. Tetapi hari berikutnya dapat juga digunakan tergantung pada rentang tanggal yang diperlukan untuk mendukung tugas tertentu.
Jay memposting 7daysclean.cmd yang berisi solusi cepat "date to seconds" untuk penerjemah baris perintah cmd.exe . Tapi itu tidak mengambil tahun kabisat diperhitungkan. JR memposting add-on untuk memperhitungkan hari kabisat di tahun berjalan, tetapi mengabaikan tahun kabisat lainnya sejak tahun dasar, yaitu sejak tahun 1970.
Saya menggunakan sejak 20 tahun tabel statis (array) dibuat sekali dengan fungsi C kecil untuk dengan cepat mendapatkan jumlah hari termasuk hari kabisat dari 1970-01-01 dalam fungsi konversi tanggal / waktu dalam aplikasi saya yang ditulis dalam C / C ++.
Metode tabel yang sangat cepat ini dapat digunakan juga dalam kode batch menggunakan perintah FOR . Jadi saya memutuskan untuk membuat kode subrutin batch GetSeconds
yang menghitung jumlah detik sejak 1970-01-01 00:00:00 UTC untuk string tanggal / waktu yang diteruskan ke rutin ini.
Catatan: Kabisat detik tidak diperhitungkan karena sistem file Windows juga tidak mendukung detik kabisat.
Pertama, tabel:
Hari sejak 1970-01-01 00:00:00 UTC untuk setiap tahun termasuk hari kabisat.
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
Menghitung detik untuk tahun 2039 hingga 2106 dengan zaman mulai 1970-01-01 hanya mungkin dengan menggunakan variabel 32-bit yang tidak ditandai, yaitu panjang yang tidak ditandatangani (atau int tidak ditandatangani) di C / C ++.
Tapi cmd.exe digunakan untuk ekspresi matematika, variabel 32-bit yang ditandatangani. Oleh karena itu nilai maksimum adalah 2147483647 (0x7FFFFFFF) yaitu 2038-01-19 03:14:07.
Informasi tahun kabisat (Tidak / Ya) untuk tahun 1970 hingga 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
Jumlah hari hingga hari pertama setiap bulan pada tahun berjalan.
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
Mengonversi tanggal ke jumlah detik sejak 1970-01-01 cukup mudah menggunakan tabel tersebut.
Tolong perhatiannya!
Format string tanggal dan waktu tergantung pada pengaturan wilayah dan bahasa Windows. Pembatas dan urutan token yang ditetapkan ke variabel lingkungan Day
, Month
dan Year
pada loop FOR pertama GetSeconds
harus disesuaikan dengan format tanggal / waktu lokal jika perlu.
Diperlukan untuk mengadaptasi string tanggal dari variabel lingkungan jika format tanggal dalam variabel lingkungan DATE berbeda dengan format tanggal yang digunakan oleh perintah FOR pada %%~tF
.
Misalnya ketika %DATE%
mengembang ke Sun 02/08/2015
sementara %%~tF
mengembang ke 02/08/2015 07:38 PM
kode di bawah ini dapat digunakan dengan memodifikasi baris 4 ke:
call :GetSeconds "%DATE:~4% %TIME%"
Ini menghasilkan passing ke subrutin saja 02/08/2015
- string tanggal tanpa 3 huruf singkatan hari kerja dan karakter spasi yang terpisah.
Sebagai alternatif, berikut dapat digunakan untuk melewati tanggal saat ini dalam format yang benar:
call :GetSeconds "%DATE:~-10% %TIME%"
Sekarang 10 karakter terakhir dari string tanggal diteruskan ke fungsi GetSeconds
dan oleh karena itu tidak masalah jika string tanggal dari variabel lingkungan DATE adalah dengan atau tanpa hari kerja selama hari dan bulan selalu dengan 2 digit dalam urutan yang diharapkan, yaitu dalam format dd/mm/yyyy
atau dd.mm.yyyy
.
Berikut ini adalah kode batch dengan menjelaskan komentar yang hanya menampilkan file mana yang akan dihapus dan file mana yang harus disimpan dalam C:\Temp
folder tree, lihat kode loop FOR pertama .
@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
Untuk kinerja yang optimal, sebaiknya hapus semua komentar, yaitu semua baris yang dimulai dengan rem setelah 0-4 spasi.
Dan array dapat dibuat juga lebih kecil, yaitu mengurangi rentang waktu dari 1980-01-01 00:00:00 menjadi 2038-01-19 03:14:07 seperti yang saat ini didukung oleh kode batch di atas misalnya ke 2015-01 -01 hingga 2019-12-31 sebagai kode di bawah ini menggunakan yang benar-benar menghapus file yang lebih lama dari 7 hari di C:\Temp
folder tree.
Selanjutnya kode batch di bawah ini dioptimalkan untuk format waktu 24 jam.
@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
Untuk informasi lebih lanjut tentang format tanggal dan waktu dan perbandingan waktu file di Windows lihat jawaban saya di Cari tahu apakah file lebih dari 4 jam dalam file batch dengan banyak informasi tambahan tentang waktu file.