标题: [日期时间] 批处理日期转数字,数字转日期 [打印本页]
作者: cutebe 时间: 2021-2-20 10:46 标题: 批处理日期转数字,数字转日期
日期转数字思路:每一年的天数累加。
公式:年数 x 365 + 闰年多出的天数 + M月D日的当年天数
核心算法同:批处理计算给定日期(年月日)是星期几
http://bbs.bathome.net/thread-57642-1-1.html- ::日期转数字函数date2num
- @echo off
- setLocal enableDelayedExpansion
-
- ::日期变数字 2021-01-23:737813
- set idate=2021-01-23
- set fdate=%idate:-=%
- call :date2num fdate nday
- echo 日期 %idate% 对应数字 %nday%
- pause
- goto :eof
- ::====完====
-
- ::计算日期的天号。参数YYYYMMDD,输出num
- :date2num formatdate index
- setlocal
- set "fdate=!%1!"
- set/a y=1%fdate:~,4%-10000,m=1%fdate:~4,2%-100,d=1%fdate:~6,2%-100
- set/a y1=y-1,m3=(m-1)*3
- set/a "leap=^!(y%%4)&^!^!(y%%100)|^!(y%%400)",T2=28+leap
- set Mdays=+31+T2+31+30+31+30+31+31+30+31+30+31
- set/a days=d!Mdays:~,%m3%!
- set/a nday=y1/4-y1/100+y1/400+y1*365+days
- endlocal&set %2=%nday%
- goto :eof
复制代码
这个相对简单些,直接转成函数形式了。
假设当前历法不变(假设很重要)!计算是从0001-01-01为第1天开始。
set/a nday=(y1/4-y1/100+y1/400)+y1*365+days
nday为天数,y为年,days为月日代表的天数;
y1/4-y1/100+y1/400 红色的为闰年数,即每个闰年比365多出的天数;
y1*365 就是粗算的年转天数。
作者: cutebe 时间: 2021-2-20 10:47
本帖最后由 cutebe 于 2021-2-20 11:17 编辑
数字转日期思路:数字按一年一年天数递减,年累加;多出的不足一年的天数换算成月份和日号。
加速:一年一年加循环次数太多,会很慢。先预估一个大致年数,循环可减少2个量级。
也是假定当前历法不变!数字也是从0001-01-01为第1天开始算起。- ::数字转日期
- @echo off
- setLocal enableDelayedExpansion
-
- :input 输入
- ::set/a num=737840 %_2021-02-19%
- set/p num=输入数字:
-
- ::计算年月日
- set/a n=num,year=1,y=n/366 %_估算年_%
- set/a ny=y/4-y/100+y/400+y*365,y+=year,n-=ny
- :iyear 精算年份。 //多出的天一年一年加入,减少循环次数
- call :Lyear n y flag leap
- if %flag%==0 goto :mday
- set/a y+=flag,n-=365+leap
- goto :iyear
- :mday 计算几月几日。 //leap在最后一次调用:Lyear函数时得出
- set/a T2=28+leap,m=1,d=n
- set Mdays=+31+T2+31+30+31+30+31+31+30+31+30+31
- for /l %%m in (36,-3,3)do (
- set/a days=0!Mdays:~,%%m!
- if %n% gtr !days! set/a m+=%%m/3,d=n-days&goto :outfor
- )
- :outfor
-
- ::显示结果
- echo/ 转换成日期 %y%年 %m%月 %d%日
- echo/
- goto :input
- ::====完====
-
- ::根据数字年号判断是否加一年及闰年
- :Lyear num year flagYearAdd leap
- setlocal
- set/a n=%1,y=%2
- set/a "leap=^!^!(y%%100)&^!(y%%4)|^!(y%%400)"
- set/a ty=365+leap,fy=0
- if %n% gtr %ty% set fy=1
- endlocal&set %3=%fy%&set %4=%leap%
- goto :eof
复制代码
核心算法说明:
set/a y=n/366 //估算年份,选用366是因为所有年份≤366天,除得的商会小于实际年数方便后面计算;
set/a ny=(y/4-y/100+y/400)+y*365 //前面的估年不准确,这里是估算年份之前的 精确天数;
:iyear 循环 //得到精确天数后,把剩余天数超过整年的部分累加到年数里;
:mday 标号下方代码 //最后剩下的不足整年的分配到月日中,算法是 给定年月日计算星期几 的逆运算,即通过月份之前天数与剩余天数对比 来获取月份。
year 函数 //判断数字是否超过一年,及当年是否闰年
数字转日期函数:num2date- ::数字转日期函数num2date
- @echo off
- setLocal enableDelayedExpansion
-
- ::set/a num=3652059 %_最大数_%
- set/a num=737840 %_2021-02-19%
- call :num2date num xdate
- set sdate=%xdate:~,4%-!xdate:~4,2!-%xdate:~6%
- echo/ 数字%num% 转换成日期 %sdate%
- pause
- goto :eof
- ::====完====
-
- ::计算数字对应的日期。参数num,输出YYYYMMDD;调用函数Lyear数字是否超过一年及闰年
- :num2date num fdate
- setlocal
- set/a n=%1,year=1,y=n/366 %_估年_%
- set/a ny=(y/4-y/100+y/400)+y*365,y+=year,n-=ny
- :iyear 精算年份。 //多出的天一年一年加入
- call :Lyear n y flag leap
- if %flag%==0 goto :mday
- set/a y+=flag,n-=365+leap
- goto :iyear
- :mday 计算几月几日。 //leap在最后一次调用:Lyear函数时得出
- set/a T2=28+leap,m=1,d=n
- set Mdays=+31+T2+31+30+31+30+31+31+30+31+30+31
- for /l %%m in (36,-3,3)do (
- set/a days=0!Mdays:~,%%m!
- if %n% gtr !days! set/a m+=%%m/3,d=n-days&goto :outfor
- )
- :outfor
- set/a fy=10000+y,fm=100+m,fd=100+d
- set fdate=%fy:~-4%!fm:~-2!%fd:~-2%
- endlocal&set %2=%fdate%
- goto :eof
-
- ::根据数字年号判断是否加一年及闰年
- :Lyear num year flagYearAdd leap
- setlocal
- set/a n=%1,y=%2
- set/a "leap=^!^!(y%%100)&^!(y%%4)|^!(y%%400)"
- set/a Ydays=365+leap,fy=0
- if %n% gtr %Ydays% set fy=1
- endlocal&set %3=%fy%&set %4=%leap%
- goto :eof
复制代码
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |