Board logo

标题: 5 个计算天数的批处理 [打印本页]

作者: 随风    时间: 2008-4-15 22:26     标题: 5 个计算天数的批处理

5 个计算天数的批处理
发现很多人需要计算 n 天前后的天数,
但是计算天数要考虑到大月小月,平年闰年。及其麻烦。
于是把我的收集整理后发出来给大家共享一下。
说明:
   收集整理: 随风 @bbs.bathome.net   2008-04-15
   第一个代码 作者:Will Sort  出自:cn-dos
   第二、三、四、个代码 作者:namejm 出自:cn-dos
   第五个为 bat 结合 vbs 代码,作者及出处都不详。
其中第一及第五个代码,输入负数为:追溯指定日期以后的天数。
第二、三、四个代码,未作测试,但输入正整数是可以的。也就是追溯指定日期以前的天数。
===========================================================================
代码一、
      作者:Will Sort
  1. :: DateDel2.bat - 删除指定路径下指定日数以前修改的文件
  2. :: 作者:Will Sort - 2005-9-2 - CMD@WinXP 出自:cn-dos
  3. :: 注意事项:变量 tian 为指定日数,昨天为1,前天为2,依次类推
  4. :: 核心算法:Ritchie Lawrence, updated 2002-08-13. Version 1.1
  5. ::
  6. @echo off & setlocal ENABLEEXTENSIONS
  7. call :Date2Day %date:~0,10% sdays
  8. rem 下行的%tian%代表天数.
  9. set /p tian=      请指定要追溯的天数:
  10. set /a sdays-=tian
  11. call :Day2Date %sdays% difdate
  12. echo.&echo.
  13. echo       指定的日期是:  %date:~0,10%
  14. echo.
  15. echo       %tian% 天前的日期是:%difdate%
  16. echo.&pause
  17. exit
  18. :Date2Day
  19. setlocal ENABLEEXTENSIONS
  20. for /f "tokens=1-3 delims=/-, " %%a in ('echo/%1') do (
  21.   set yy=%%a & set mm=%%b & set dd=%%c
  22. )
  23. set /a dd=100%dd%%%100,mm=100%mm%%%100
  24. set /a z=14-mm,z/=12,y=yy+4800-z,m=mm+12*z-3,j=153*m+2
  25. set /a j=j/5+dd+y*365+y/4-y/100+y/400-2472633
  26. endlocal&set %2=%j%&goto :EOF
  27. :Day2Date
  28. setlocal ENABLEEXTENSIONS
  29. set /a i=%1,a=i+2472632,b=4*a+3,b/=146097,c=-b*146097,c/=4,c+=a
  30. set /a d=4*c+3,d/=1461,e=-1461*d,e/=4,e+=c,m=5*e+2,m/=153,dd=153*m+2,dd/=5
  31. set /a dd=-dd+e+1,mm=-m/10,mm*=12,mm+=m+3,yy=b*100+d-4800+m/10
  32. (if %mm% LSS 10 set mm=0%mm%)&(if %dd% LSS 10 set dd=0%dd%)
  33. endlocal&set %2=%yy%-%mm%-%dd%&goto :EOF
复制代码

===========================================================================
代码二、
   以下三个代码作者全是 namejm
  1. :: 作者: namejm   荣誉版主 出自:cn-dos
  2. @echo off
  3. :: 求N天前的日期
  4. :: 思路:
  5. ::   模拟手工运算,用日期数减去天数,差值为负时向高位借1。
  6. :: 特点:
  7. ::   代码简洁,容易理解,速度快慢取决于指定的天数大小
  8. :: 日期可以带星期,但是,必须以年月日的顺序排列
  9. :: 年份必须是四位,否则会出错
  10. @echo off
  11. :Main
  12. cls
  13. set day=%date%
  14. set days=0
  15. echo.&echo.
  16. echo       指定的日期是:%day%
  17. echo.
  18. set /p input=      请指定要追溯的天数:
  19. setlocal enabledelayedexpansion
  20. :: 提取日期
  21. for /f "tokens=1-3 delims=-/. " %%i in ("%day%") do (
  22.     set /a sy=%%i, sm=100%%j %% 100, sd=100%%k %% 100
  23. )
  24. set /a sd-=input
  25. if %sd% leq 0 call :count
  26. cls
  27. echo.&echo.
  28. echo       指定的日期是:%day%
  29. echo.
  30. set sm=0%sm%
  31. set sd=0%sd%
  32. echo       %input% 天前的日期是:%sy%-%sm:~-2%-%sd:~-2%
  33. pause>nul
  34. goto Main
  35. :count
  36. set /a sm-=1
  37. if !sm! equ 0 set /a sm=12, sy-=1
  38. call :days
  39. set /a sd+=days
  40. if %sd% leq 0 goto count
  41. goto :eof
  42. :days
  43. :: 获取指定月份的总天数
  44. set /a leap="^!(sy %% 4) & ^!(^!(sy %% 100)) | ^!(sy %% 400)"
  45. set /a max=28+leap
  46. set num=0
  47. set str=31 %max% 31 30 31 30 31 31 30 31 30 31
  48. for %%i in (%str%) do (
  49.     set /a num+=1
  50.     if %sm% equ !num! set days=%%i&goto :eof
  51. )
  52. goto :eof
复制代码

===========================================================================
代码三、
  1. @echo off
  2. :: 作者: namejm   荣誉版主 出自:cn-dos
  3. :: 求N天前的日期
  4. :: 思路:
  5. ::   把当前日期转换为天数
  6. ::   用当前天数减去N天
  7. ::   把结果再转换为日期
  8. :: 具体操作是:
  9. ::   逐年计算天数
  10. :: 特点:
  11. ::    代码简洁,容易理解,速度较慢,但是不受指定天数大小的影响
  12. setlocal enabledelayedexpansion
  13. :Main
  14. cls
  15. :: 日期可以带星期,但是,必须以年月日的顺序排列
  16. :: 年份必须是四位,否则会出错
  17. set day=%date%
  18. set days=0
  19. echo.&echo.
  20. echo       指定的日期是:%day%
  21. echo.
  22. set /p input=      请指定要追溯的天数:
  23. rem ========把指定日期转换为天数========
  24. :: 提取日期
  25. for /f "tokens=1-3 delims=-/. " %%i in ("%day%") do (
  26.     set /a sy=%%i, sm=100%%j %% 100, sd=100%%k %% 100
  27. )
  28. :: 把年份转化为天数
  29. for /l %%i in (1,1,%sy%) do (
  30.     set /a leap="^!(%%i %% 4) & ^!(^!(%%i %% 100)) | ^!(%%i %% 400)"
  31.     set /a days=days+365+leap
  32. )
  33. :: 把月份转化为天数
  34. set /a num=0, mday=0, max=28+leap
  35. set str=0 31 %max% 31 30 31 30 31 31 30 31 30
  36. for %%i in (%str%) do (
  37.     set /a num+=1
  38.     if !num! leq !sm! set /a mday+=%%i
  39. )
  40. set /a days=days+mday+sd
  41. set /a days-=input
  42. rem ========把天数转换为日期========
  43. :: 获取年份
  44. for /l %%i in (1,1,%sy%) do (
  45.     set /a leap="^!(%%i %% 4) & ^!(^!(%%i %% 100)) | ^!(%%i %% 400)"
  46.     set /a days_tmp=365+leap
  47.     if !days! gtr !days_tmp! (
  48.         set /a days-=days_tmp
  49.         set y=%%i
  50.     )
  51. )
  52. :: 获取月份及日期
  53. set /a m=1, max=28+%leap%
  54. set str=31 %max% 31 30 31 30 31 31 30 31 30
  55. for %%i in (%str%) do (
  56.     if !days! gtr %%i (
  57.         set /a days-=%%i
  58.         set /a m+=1
  59.     ) else goto next
  60. )
  61. :next
  62. set m=0%m%
  63. set d=0%days%
  64. cls
  65. echo.&echo.
  66. echo       指定的日期是:%day%
  67. echo.
  68. echo       %input% 天前的日期是:%y%-%m:~-2%-%d:~-2%
  69. pause>nul
  70. goto Main
复制代码

===========================================================================
代码四、
  1. @echo off
  2. :: 作者: namejm   荣誉版主 出自:cn-dos
  3. :: 求N天前的日期
  4. :: 思路:
  5. ::   把当前日期转换为天数
  6. ::   用当前天数减去N天
  7. ::   把结果再转换为日期
  8. :: 具体操作是:
  9. :    先按照每年365天计算,然后再计算闰年的个数
  10. ::   最后再做转换
  11. :: 特点:
  12. ::   代码复杂,不便于理解,但是速度很快
  13. :: 计算上还存在bug,可以用 11111 来和头两个做对比测试,暂时没时间更新
  14. setlocal enabledelayedexpansion
  15. :Main
  16. cls
  17. :: 日期可以带星期,但是,必须以年月日的顺序排列
  18. :: 年份必须是四位,否则会出错
  19. set day=2007-01-02
  20. set /a days=0, sum=0
  21. echo.&echo.
  22. echo       指定的日期是:%day%
  23. echo.
  24. set /p input=      请指定要追溯的天数:
  25. rem =======把日期转换为天数=======
  26. :: 提取日期
  27. for /f "tokens=1-3 delims=/-. " %%i in ("%day%") do (
  28.     set /a sy=%%i, sm=100%%j %% 100, sd=100%%k %% 100, y=%%i
  29. )
  30. :: 把年份抓换为天数
  31. set num=0
  32. if %sy% lss 400 goto next1
  33. call :leap_num
  34. :next1
  35. set /a leap_num=sy/4-num
  36. :: 把月份转换为天数
  37. set /a leap="^!(sy %% 4) & ^!(^!(sy %% 100)) | ^!(sy %% 400)"
  38. set /a max=28+leap
  39. set num=0
  40. set str=31 %max% 31 30 31 30 31 31 30 31 30 31
  41. for %%i in (%str%) do (
  42.     set /a num+=1
  43.     if !num! lss %sm% set /a sum+=%%i
  44. )
  45. set /a days=365*sy+leap_num+sum+sd
  46. set /a days-=input
  47. rem =======把天数转换为日期=======
  48. :: 获取年份
  49. set /a y=days/365
  50. set /a mod1=days %% 365
  51. call :leap_num
  52. set /a mod2=mod1-leap_num
  53. :loop2
  54. if %mod2% lss 0 (
  55.     set /a y-=1
  56.     set /a mod2=365+mod2
  57. ) else goto next2
  58. goto loop2
  59. :: 获取月份及日期
  60. :next2
  61. set /a m=1, days=mod2+1, max=28+%leap%
  62. set str=31 %max% 31 30 31 30 31 31 30 31 30
  63. for %%i in (%str%) do (
  64.     if !days! gtr %%i (
  65.         set /a days-=%%i
  66.         set /a m+=1
  67.     ) else goto next3
  68. )
  69. :next3
  70. set m=0%m%
  71. set d=0%days%
  72. cls
  73. echo.&echo.
  74. echo       指定的日期是:%day%
  75. echo.
  76. echo       %input% 天前的日期是:%y%-%m:~-2%-%d:~-2%
  77. pause>nul
  78. goto Main
  79. :leap_num
  80. :: 计算能被100整除但是不能被400整除的年次
  81. set /a y_tmp=(%y:~0,1%%y%-%y%)/10
  82. set num=0
  83. :loop1
  84. set /a mod=y_tmp %% 400
  85. if %mod% neq 0 set /a num+=1
  86. set /a y_tmp-=100
  87. if %y_tmp% geq 100 goto loop1
  88. set /a leap_num=y/4-num
  89. goto :eof
复制代码

===========================================================================
代码五、
  用 vbs 代码可以更简单。但是需创建 tmptmp.vbs 临时文件。
  1. @echo off
  2. set /p _tian=      请指定要追溯的天数:
  3. >tmptmp.vbs echo wscript.echo dateadd("d",-%_tian%,date)
  4. for /f "tokens=1,2,3* delims=-" %%i in ('cscript /nologo tmptmp.vbs') do (
  5.      set /a y=%%i,m=100%%j%%100,d=100%%k%%100
  6. )
  7. set "difdate=%y%-%m%-%d%"
  8. del/q tmptmp.vbs
  9. cls&echo.&echo.
  10. echo       指定的日期是:  %date:~0,10%
  11. echo.
  12. echo       %_tian% 天前的日期是:%difdate%
  13. echo.&pause&exit
复制代码

[ 本帖最后由 随风 于 2008-4-15 22:32 编辑 ]
作者: fml520    时间: 2008-4-15 22:55

好东西,顶起来 啊~~~~~~
作者: wankoilz    时间: 2008-6-5 14:05

第一个看不大懂........
我再来补充两个嵌vbs的:
第一个是我的,不用生成临时文件:
  1. ' 2>nul 3>nul&@echo off&cls
  2. '&if not "%1"=="" goto on
  3. '&set/p day=请输入要追溯的天数:
  4. '&start wscript.exe /nologo /e:vbs %0 %day%
  5. '&exit
  6. set oshell=createobject("wscript.shell")
  7. d=wscript.arguments(0)
  8. add=dateadd("d",-d,date)
  9. myweekday=weekdayname(weekday(add))
  10. s=wscript.scriptfullname
  11. oshell.run "cmd /c"&""""&s&""""&" "&d&" "&add&" "&myweekday,1,false
  12. :on error resume next
  13. '&title 追溯日期&echo 今天是: %date%&echo.&echo %1天前是: %2 %3&echo.&pause&%0
复制代码
第二个来自bbs.verybat.cn ,出自 清风09,有临时文件:
  1. @echo off
  2. set /p d=请输入要追溯的天数:
  3. mshta vbscript:createobject("scripting.filesystemobject").opentextfile("wind.txt",2,true).writeline(dateadd("d",-%d%,date))(window.close)
  4. for /f %%a in (wind.txt) do echo %d%天前为:%%a
  5. pause>nul & del wind.txt
复制代码

[ 本帖最后由 wankoilz 于 2008-6-5 15:21 编辑 ]
作者: garyng    时间: 2011-8-23 20:27

好用~
收藏了~
作者: xudaweb    时间: 2011-8-31 03:27

每个都测试了下,就代码5有问题。
作者: zsl200911    时间: 2013-2-4 16:02

学习一下,谢谢




欢迎光临 批处理之家 (http://bathome.net./) Powered by Discuz! 7.2