[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖
本帖最后由 CrLf 于 2012-4-4 01:17 编辑

原型:
  1. set/a days=d-719446+30*m+m/9*-~m/2+!(m/9)*m/2+!!(m/3)*(!(y%%4)-!(y%%100)+!(y%%400)-2)+y*365+~-y/4-~-y/100+~-y/400
  2. rem 日期转天数
  3. set/a d+=719050,d-=d/1461-d/36524+d/146097,y=d/365+1,r=!(y%%4)-!(y%%100)+!(y%%400),d+=(d%%=365)/(212+r)*30+r,d+=!!(d/(59+r))*(2-r),m=d/61*2+d%%61/31,d-=m*61/2+m*61%%2-1,m+=1-m/8
  4. rem 天数转日期
  5. set /a m+=!(m/=3)*12,week=(d+2*m+3*(m+1)/5+(y-=m/13)+y/4-y/100+y/400+1)%%7
  6. rem 日期转星期
复制代码

TOP

google:
Date calculation algorithm
有些有价值的参考
1

评分人数

TOP

我先来:
Question1:给定两个时间(同一天),求相隔的秒数
这个应该是最简单的;
思路描述:
先看看怎么计算327-179
(3-1)*100+(2-7)*10+(7-9)*1
1小时=3600秒
1分钟=60秒
类比得到h1,f1,s1 到 h2,f2,s2
相隔的秒数=(h2-h1)*3600+(f2-f1)*60+s2-s1
  1. set/a y=2012,m=4,d=3,h1=1,f1=2,s1=9
  2. set/a                h2=1,f2=3,s2=9
  3. rem -------------------
  4. set out=(h2-h1)*3600+(f2-f1)*60+s2-s1
  5. rem -------------------
  6. echo %out%
  7. rem 输出值out=60
复制代码

TOP

本帖最后由 plp626 于 2012-4-15 09:37 编辑

{~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
本贴主要讨论时间日期计算的算法思想(几乎纯数学,外加set/a运算技巧)
可参照 HAT翻译了Ritchie Lawrence 的时间日期函数库;为引子,开启大家思路;

方便交流,做如下约定:
一个时间变量(可以称作复合型变量)由6个整数组成,分别为:【年数,月数,日数,时数,分数,秒数】
  1. :: 方便讨论这6个整数分别用如下字母表示[y,m,d,h,f,s]
  2. y取值范围[-10000,10000];
  3. (暂时不考虑y为负值的情形,只考虑公元1年1月1日之后的情形;视难度而定)
  4. m取值范围[1,12]
  5. d取值范围[1,31]
  6. h取值范围[0,23]
  7. f取值范围[0,59]
  8. s取值范围[0,59]
  9. :: 比如 2012-04-03,1:02:09秒这个时间对应的值为 y=2012,m=4,d=3,h=1,f=2,s=9
复制代码
本贴重点是算法思想,阐述思路是重点;
代码虽然作为载体不很重要,但也请给出最简短高效的实现代码;
(在便于阅读的条件下,一行set/a 实现最好)

主要解决一下问题;
(一)给定两个时间,求其相隔的天数;或者秒数
Q1:
     y1,m1,d1,h1,f1,s1 (初时间); y1,m1,d1,h2,f2,s2(末时间) // 初末时间符合客观现实
     求其相隔多少秒sec
  1. :fun1
  2. set/a y=2012,m=4,d=3,h1=1,f1=2,s1=9
  3. set/a                h2=1,f2=3,s2=9
  4. rem ---- 你的代码1 -----
  5. echo %out%
  6. rem 输出值out=60
复制代码
Q2:  
     y1,m1,d1,h1,f1,s1 (初时间); y2,m2,d2,h1,f1,s1(末时间) // 初末时间符合客观现实
     求其相隔多少天day
  1. :fun2
  2. set/a y1=2012,m1=4,d1=3,h=1,f=2,s=9
  3. set/a y2=2012,m2=5,d2=3
  4. rem ---- 你的代码1 -----
  5. echo %out%
  6. rem 输出值out=31
复制代码
Q3:
     y1,m1,d1,h1,f1,s1 (初时间); y2,m2,d2,h2,f2,s2(末时间) // 初末时间符合客观现实
     求其相隔多少天day+多少秒sec (day,sec 为 非负数,day范围[0,+2147483647]sec范围为[0,86399])
  1. :fun3
  2. set/a y1=2012,m1=4,d1=3,h1=1,f1=2,s1=9
  3. set/a y2=2012,m2=4,d2=5,h2=1,f2=2,s2=10
  4. rem ---- 你的代码1 -----
  5. echo %out%
  6. rem 输出值out=2 1
复制代码
(二)给定一个时间,y,m,d,h,f,s 求其 x天或x秒之后的时间
Q4:
       给定 y,m,d,h,f,s;求x天后的;y,m,d,h,f,s (x为负数表示之前,x范围:[-2147483647, +2147483648])
  1. :fun4
  2. set/a y=2012,m=4,d=3,h=1,f=2,s=9
  3. set/a x=-4
  4. rem ---- 你的代码 -----
  5. echo %out%
  6. rem 输出值out=2012 3 30 1 2 9
复制代码
Q5:
   给定 y,m,d,h,f,s;求x秒后的;y,m,d,h,f,s (x为负数表示之前,x范围:[-86399, +86399])
  1. :fun5
  2. set/a y=2012,m=4,d=3,h=1,f=2,s=9
  3. set/a x=-61
  4. rem ---- 你的代码 -----
  5. echo %out%
  6. rem 输出值out=2012 4 3 1 1 8
复制代码
(三)给定一个日期,求其星期数
  1. :fun6 给定一个日期,求其星期数
  2. set/a y=2012,m=4,d=3
  3. rem ---- 你的代码 -----
  4. echo %out%
  5. rem 输出值out=2
复制代码
为建立适合cmd的时间变量数据结构,增加一个成员;跑秒,即百分之一秒;

这样一个时间变量有7个成员(年,月,日,时,分,秒,跑秒),为方便交流约定分别用字母(y,m,d,h,f,s,p)表示;
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~}

回复 7# CrLf
Q1就是Q3的特殊情形(同一天内的两时间差)
Q2也是Q3的特殊情形(同一时分秒下,两日期相隔的天数)
对于你说的问题我不够秒数不细致造成误会;sec取值范围为[0,86399](已更新);
把第一类问题分解成Q1,Q2,是有原因的;
一天=86400秒,秒数可以转换为天数,天数也能转换为秒数,那么求时间差,给出day+sec不是多次一举?
非也,set/a 能支持的最大数值2147483647,2147483647sec=24855day=58year
为了能兼容表示超过58年的情形,用两个数表示时间差,day和sec;day相当于时间差值的高位,sec相当于时间差值的低位;
所以,sec的取值范围为[0,86399]
第一类问题的核心是Q2,这里推荐大家参看15楼的思想;
对于第二类问我还没好思路,大家继续参看15楼的思想,交流下;

把算法思想吃透了,代码真就是工具了;
-----------------------------------------------------------

回复 5# CrLf

只测试了你的天数转日期,是把1969-9-11作为参考日期的第0天;只见代码不见思想;
  1. :d2ymd <day> <ret:y> <ret:m> <ret:d>
  2. @echo off
  3. :d2ymd
  4. setlocal enabledelayedexpansion
  5. set/a d=%1
  6. set/a "d+=719050,d-=d/1461-d/36524+d/146097,y=d/365+1,r=^!(y%%4)-^!(y%%100)+^!(y%%400),d+=(d%%=365)/(212+r)*30+r,d+=^!^!(d/(59+r))*(2-r),m=d/61*2+d%%61/31,d-=m*61/2+m*61%%2-1,m+=1-m/8"
  7. endlocal&if %4. neq . (set %2=%y%&set %3=%m%&set %4=%d%)else echo %y% %m% %d%
复制代码
保存为d2ymd.bat,发现不少bug:
  1. ->d2ymd 841
  2. 1971 12 31
  3. ->d2ymd 842
  4. 1972 1 2
  5. ->d2ymd 1223
  6. 1973 1 16
  7. ->d2ymd 1222
  8. 1973 1 16
  9. 还有很多bug。。。
复制代码
---------------------------------------------

TOP

返回列表