本帖最后由 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
复制代码
|