首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

批次檔日期時間運算深度解析:從秒數加減到跨月跨年

     編輯:關於C語言

批次檔原生只支援十進位整數運算(set /a),卻要處理 60 進位(分/秒)、24 進位(時)、12 進位(月)、不定天數(月/閏年)的時間計算,難度極高。本文系統拆解「去零→十進位運算→進位轉換→補零」四步法,並提供可直接引用的子程式::AddSec、:SubSec、:IsLeapYear、:DaysInMonth。

核心難點與對策

難點對策
時間元件前導零導致八進位誤判(08、09)前綴 1 再取模 100:set /a m=1%%m%%100
小時可能為空格(單位數)set "h=%time:~,2%" 後 set "h=%h: =0%" 替換空格為零
進位制混雜(秒/分 60、時 24、月 12、日 28/29/30/31)統一轉為「總秒數」或「總天數」運算,再反推
閏年判斷(能被 400 整除、或被 4 整除但非 100 倍數)子程式 :IsLeapYear 回傳 1/0

關鍵技巧:去零與補零

:: 去零:將 "08" → 8,避免八進位
set /a m=1%m%%%100, s=1%s%%%100

:: 運算後補零:確保兩位數顯示
set "m=0%m%" & set "m=%m:~-2%"
set "s=0%s%" & set "s=%s:~-2%"

範例:目前時間往後推 1000 秒

@echo off & setlocal enabledelayedexpansion
set "h=%time:~,2%" & set "h=%h: =0%"
set /a "m=1%time:~3,2%%%100, s=1%time:~6,2%%%100"
echo 目前時間 %h%:%m%:%s%

for /l %%a in (1,1,1000) do (
    set /a s+=1
    if !s! equ 60 set /a s=0, m+=1
    if !m! equ 60 set /a m=0, h+=1
    if !h! equ 24 set /a h=0
)
set "m=0%m%" & set "m=%m:~-2%"
set "s=0%s%" & set "s=%s:~-2%"
echo 1000秒後 %h%:%m%:%s%
pause > nul

進階:跨日期回溯/推算(含閏年處理)

完整程式碼篇幅較長,核心邏輯:

  1. 將輸入日期時間拆解為 Y,M,D,H,M,S。
  2. 計算總天數差 num_d = 秒數/86400、剩餘秒數 num_h = 秒數%%86400。
  3. 逐日遞減/遞增:D-=1,若 D==0 呼叫 :PrevMonth 取得上月天數(含閏年 2 月判斷)。
  4. 逐秒遞減/遞增:處理時分秒進位。
:IsLeapYear  <-- 年份在 %y%
set /a a=%y%%%4, b=%y%%%100, c=%y%%%400, _2=28
if %b% equ 0 (if %c% equ 0 set /a _2+=1) else (if %a% equ 0 set /a _2+=1)
set _days=%_2% & goto :eof

:DaysInMonth <-- 月份在 %mo%, 年份在 %y%
if %mo%==2 call :IsLeapYear & set _days=%_2% & goto :eof
for %%a in (1 3 5 7 8 10 12) do if %mo%==%%a set _days=31 & goto :eof
for %%a in (4 6 9 11) do if %mo%==%%a set _days=30 & goto :eof
goto :eof

建議

  • 單純秒數加減:用上述「總秒數法」即可。
  • 跨月跨年、業務級日期運算:強烈建議呼叫 PowerShell (Get-Date).AddDays(-30) 或 VBScript DateAdd,批次檔維護成本極高且易出錯。
  • 若必須純批次,將上述子程式模組化放入共用 lib_datetime.bat,主腳本 call lib_datetime.bat 後直接使用 :AddDays 等標籤。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved