Có rất nhiều câu hỏi liên quan đến ngày / thời gian liên quan để giải quyết với tệp bó. Nhưng trình thông dịch dòng lệnh cmd.exe không có chức năng tính toán ngày / giờ. Rất nhiều giải pháp hoạt động tốt sử dụng các ứng dụng hoặc tập lệnh điều khiển bổ sung đã được đăng ở đây, trên các trang khác của Stack Overflow và trên các trang web khác.
Phổ biến cho các hoạt động dựa trên ngày / giờ là yêu cầu chuyển đổi chuỗi ngày / giờ thành giây kể từ một ngày xác định. Rất phổ biến là 1970-01-01 00:00:00 UTC. Nhưng bất kỳ ngày nào sau đó cũng có thể được sử dụng tùy thuộc vào phạm vi ngày cần thiết để hỗ trợ cho một nhiệm vụ cụ thể.
Jay đã đăng 7daysclean.cmd chứa giải pháp "ngày đến giây" nhanh chóng cho trình thông dịch dòng lệnh cmd.exe . Nhưng nó không mất năm nhuận chính xác vào tài khoản. JR đã đăng một tiện ích bổ sung cho ngày nhuận trong năm hiện tại, nhưng bỏ qua các năm nhuận khác kể từ năm cơ sở, tức là kể từ năm 1970.
Tôi sử dụng từ 20 năm bảng tĩnh (mảng) được tạo một lần với hàm C nhỏ để nhanh chóng nhận được số ngày, kể cả ngày nhuận từ 1970-01-01 trong các hàm chuyển đổi ngày / giờ trong các ứng dụng của tôi được viết bằng C / C ++.
Phương pháp bảng rất nhanh này cũng có thể được sử dụng trong mã hàng loạt bằng lệnh FOR . Vì vậy, tôi quyết định mã hóa chương trình con hàng loạt GetSeconds
tính toán số giây kể từ 1970-01-01 00:00:00 UTC cho chuỗi ngày / thời gian được truyền cho thói quen này.
Lưu ý: Không tính đến giây nhuận vì các hệ thống tệp Windows cũng không hỗ trợ giây nhuận.
Đầu tiên, các bảng:
Ngày kể từ 1970-01-01 00:00:00 UTC cho mỗi năm bao gồm cả ngày nhuận.
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
Việc tính các giây cho năm 2039 đến 2106 với epoch bắt đầu 1970-01-01 chỉ có thể bằng cách sử dụng biến 32 bit không dấu, tức là dài không dấu (hoặc int unsign) trong C / C ++.
Nhưng cmd.exe sử dụng cho các biểu thức toán học một biến 32 bit đã ký. Do đó, giá trị tối đa là 2147483647 (0x7FFFFFFF) là 2038-01-19 03:14:07.
Thông tin năm nhuận (Không / Có) trong các năm 1970 đến 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
Số ngày đến ngày đầu tiên của mỗi tháng trong năm hiện tại.
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
Chuyển đổi một ngày thành số giây kể từ 1970-01-01 khá dễ dàng bằng cách sử dụng các bảng đó.
Xin chú ý!
Định dạng của chuỗi ngày và giờ phụ thuộc vào cài đặt ngôn ngữ và khu vực của Windows. Delimiters và thứ tự của thẻ gán cho các biến môi trường Day
, Month
và Year
trong lần đầu tiên CHO vòng lặp của GetSeconds
phải được điều chỉnh để định dạng ngày / giờ địa phương nếu cần thiết.
Cần điều chỉnh chuỗi ngày của biến môi trường nếu định dạng ngày trong biến môi trường DATE khác với định dạng ngày được sử dụng bởi lệnh FOR on %%~tF
.
Ví dụ: khi %DATE%
mở rộng sang Sun 02/08/2015
trong khi %%~tF
mở rộng 02/08/2015 07:38 PM
mã bên dưới có thể được sử dụng với sửa đổi dòng 4 thành:
call :GetSeconds "%DATE:~4% %TIME%"
Điều này dẫn đến việc chuyển sang chương trình con chỉ 02/08/2015
- chuỗi ngày không có 3 chữ cái viết tắt của ngày trong tuần và ký tự khoảng trắng phân cách.
Cách khác có thể được sử dụng để vượt qua ngày hiện tại ở định dạng chính xác:
call :GetSeconds "%DATE:~-10% %TIME%"
Bây giờ 10 ký tự cuối cùng từ chuỗi ngày được truyền vào hàm GetSeconds
và do đó, không có vấn đề gì nếu chuỗi ngày của biến môi trường DATE có hoặc không có ngày trong tuần miễn là ngày và tháng luôn có 2 chữ số theo thứ tự dự kiến, nghĩa là theo định dạng dd/mm/yyyy
hoặc dd.mm.yyyy
.
Dưới đây là mã bó với giải thích các bình luận chỉ xuất ra tệp nào cần xóa và tệp nào sẽ giữ trong C:\Temp
cây thư mục, xem mã của vòng lặp FOR đầu tiên .
@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
Để có hiệu suất tối ưu, tốt nhất là xóa tất cả các nhận xét, tức là tất cả các dòng bắt đầu bằng rem sau 0-4 khoảng trắng hàng đầu.
Và các mảng có thể được thực hiện cũng nhỏ hơn, tức là giảm phạm vi thời gian từ 1980-01-01 00:00:00 đến 2038-01-19 03:14:07 như được hỗ trợ bởi mã lô ở trên, ví dụ như 2015-01 -01 đến 2019-12-31 như mã dưới đây sử dụng để thực sự xóa các tệp cũ hơn 7 ngày trong C:\Temp
cây thư mục.
Hơn nữa mã lô dưới đây được tối ưu hóa cho định dạng thời gian 24 giờ.
@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
Để biết thêm thông tin về định dạng ngày và thời gian và so sánh thời gian tệp trên Windows, hãy xem câu trả lời của tôi trên Tìm hiểu xem tệp có cũ hơn 4 giờ trong tệp bó với nhiều thông tin bổ sung về thời gian tệp hay không.