标题: [日期时间] 批处理怎样输出两个指定日期之间的所有日期? [打印本页]
作者: DAIC 时间: 2011-6-4 00:33 标题: 批处理怎样输出两个指定日期之间的所有日期?
本帖最后由 DAIC 于 2011-6-11 22:13 编辑
开始日期:1810-01-01
结束日期:2010-01-01
希望得到的结果(总共73050行):
1810-01-01
1810-01-02
1810-01-03
...
2010-01-01
15楼的结果:
c:\Test>timeit test.bat
Elapsed Time: 0:00:34.590
Process Time: 0:00:23.212
28楼的结果:
c:\Test>timeit test.bat
Elapsed Time: 0:00:19.345
Process Time: 0:00:11.778
作者: mxxcgzxxx 时间: 2011-6-4 09:45
参考:http://bbs.bathome.net/thread-12558-1-1.html
可以把日期看成一个大数18990101~19990101之间的数去较对正误就行了!
一个FOR+一个CALL把他们的程序拿来就行了呵
作者: batman 时间: 2011-6-4 10:18
直接输出还是不要用call,call太影响效率了。。。
作者: mxxcgzxxx 时间: 2011-6-4 11:21
本帖最后由 mxxcgzxxx 于 2011-6-4 11:28 编辑
- @echo off
- set 正模式=
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[1-9]0[1-9]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[1-9]1[0-9]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[^02]2[0-9]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]022[0-8]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[13578]3[0-1]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[469]30$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1[0-2]0[1-9]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1[0-2][12][0-9]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1[02]3[0-1]$"
- set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]1130$"
- set "正模式=%正模式% ^[1-2][0-9][13579][26]0229$"
- set "正模式=%正模式% ^[1-2][0-9][2468][048]0229$"
- set "正模式=%正模式% ^[1-2][0-9][02468][48]0229$"
- set "正模式=%正模式% ^[02468][048]000229$"
- set "正模式=%正模式% ^[13579][26]000229$"
-
-
- :loop
- set /p 开始日期=按yyyymmdd格式输入开始日期:
- echo.%开始日期%|findstr "%正模式%">nul && set "a=%开始日期%" || goto :loop
- :loop1
- set /p 结束日期=按yyyymmdd格式输入结束日期:
- echo.%开始日期%|findstr "%正模式%">nul && cls || goto :loop1
- if %结束日期% lss %开始日期% echo 结束日期小于开始日期! & goto:loop1
-
- :1
- if %a:~4,2%==13 set /a a=a/10000*10000+9999
- if %a:~6,2%==32 set /a a=a/100*100+99
- echo.%a%|findstr "%正模式%">nul && echo %a%
- if %a%==%结束日期% goto :2
- set /a a+=1
- goto :1
- :2
- pause>nul
- goto :loop
复制代码
作者: CrLf 时间: 2011-6-4 11:26
@echo off & setlocal enabledelayedexpansion
set 正模式=
set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[1-9]0[1-9]$"
set "正模式=%正模式% ^[1-2][0-9][0-9][0-9]0[1-9]1[0-9]$"
set "正模式=%正模式% ^[1 ...
mxxcgzxxx 发表于 2011-6-4 11:21
提示一下,可以这样输出:- (@for /l %%a in (start 1 end) do @echo %%a)|findstr "正则"
复制代码
如果日期很多的话,这应该是效率最高的办法了
另一种思路是也许可以用for /l嵌套,采用年循环、月循环、日循环的方式一次性输出正确日期,日期比较少时应该野不慢
作者: mxxcgzxxx 时间: 2011-6-4 11:31
本帖最后由 mxxcgzxxx 于 2011-6-4 11:33 编辑
我没采用FOR是因为13~99月那里很浪费时间,现在改了下取消了变量延时开关会更快点吧
作者: DAIC 时间: 2011-6-6 00:15
4# mxxcgzxxx
这个代码运行了六七分钟,才刚刚跑到1926年,怎样才能提高速度呢?
作者: namejm 时间: 2011-6-6 00:31
看看这个帖子:
按日期早晚顺序列出指定范围内的所有日期
http://bbs.bathome.net/viewthread.php?tid=7526
作者: CrLf 时间: 2011-6-6 12:31
本帖最后由 zm900612 于 2011-6-6 13:03 编辑
这个非常快- @echo off
- (cmd /q /v:on /c "for /l %%a in (1990 1 2012) do (for /l %%b in (1 1 12) do (for /l %%c in (1 1 31) do ((set "m=10%%b"&set "d=10%%c")&echo %%a!m:~-2!!d:~-2!)))")|findstr /ve "0[2469]31 0230 1131 [02468][048]0229 [13579][26]0229 [02468][048]000229 [13579][26]000229"
- pause
复制代码
为了省些代码只好弄成这个样子了...易读性不是很强,但是思路其实很简单,就是先输出所有有可能合法的日期,再用findstr排除不合法日期...
作者: DAIC 时间: 2011-6-6 12:48
8# namejm
http://bbs.bathome.net/viewthrea ... muid=38107#pid49141
这个代码看不懂,能否教一下怎么设置开始日期和结束日期?
作者: DAIC 时间: 2011-6-6 12:52
9# zm900612
有问题:
19000228
19000230
19000301
作者: CrLf 时间: 2011-6-6 13:03
漏了排除2月30,已修正
作者: batman 时间: 2011-6-6 13:08
本帖最后由 batman 于 2011-6-6 13:21 编辑
9# zm900612
写个setlocal enabledelayedexpansion就这么难?非要用cmd /vn,效率我想前者还是要快一点点点吧。。。
20000229非法,哈哈。。。
作者: CrLf 时间: 2011-6-6 13:24
13# batman
通道之前存在语块时,语块中的内容相当于直接输入到cmd窗口中运行,此时变量延迟是没有效果的,若要用!str!这样的变量,唯有使用cmd /vn来作为语块执行的媒介,而cmd /c是以参数的形式接收要执行的内容,所以无法换行...
整百年份有判断,不过逻辑错误,好像判断反了
作者: batman 时间: 2011-6-6 14:24
本帖最后由 batman 于 2011-6-6 16:08 编辑
老实人做老实事:- @echo off&setlocal enabledelayedexpansion
- echo,&set /p start=请输入开始日期(形如2000-03-21):
- echo,&set /p end=请输入结束日期(形如2000-03-21):
- cls&echo,&echo,&echo,&echo,&echo 程序正在运行中,请稍候。。。
- set /a sy=%start:~,4%,sm=1%start:~5,2%%%100,sd=1%start:~8,2%%%100,ey=%end:~,4%,em=1%end:~5,2%%%100,ed=1%end:~8,2%%%100,a=31
- for %%a in (1 3 5 7 8 10 12 4 6 9 11) do (
- if %%a equ 4 set /a a-=1
- set /a _%%a=a
- )
- (for /l %%a in (%sy%,1,%ey%) do (
- set /a "_2=^!(%%a%%4)&^!(^!(%%a%%100))|^!(%%a%%400)+28"
- set /a a=1,b=12
- if "%%a" equ "%sy%" set /a a=sm
- if "%%a" equ "%ey%" set /a b=em
- for /l %%b in (!a!,1,!b!) do (
- set /a c=1,d=_%%b
- if "%%a%%b" equ "%sy%%sm%" set /a c=sd
- if "%%a%%b" equ "%ey%%em%" set /a d=ed
- for /l %%c in (!c!,1,!d!) do (
- for %%d in (%%b %%c) do set ".%%d=0%%d"&set ".%%d=!.%%d:~-2!"
- echo %%a-!.%%b!-!.%%c!
- )
- )
- ))>list.txt
- start list.txt
复制代码
作者: 随风 时间: 2011-6-6 15:24
15# batman
set /a "_2=^!(%%a%%4)&^!(^!(^!%%a%%100))|^!(%%a%%400)+28"
笔误了
作者: batman 时间: 2011-6-6 16:09
16# 随风
确实是的
作者: CrLf 时间: 2011-6-7 12:14
本帖最后由 zm900612 于 2011-6-7 12:19 编辑
这个思路可以有掌声吧?...- @echo off&setlocal enabledelayedexpansion
- set min=19900612
- set max=20121125
-
- for /l %%a in (31 -1 1) do (
- set tmp=0%%a
- set md=!md! !tmp:~-2!
- )
- ::先将个位数转换为0开头,避免在循环中计算
-
- set /a y1=%min:~0,-4%,y2=%max:~0,-4%,m1=1%min:~-4,2%-100,m2=1%max:~-4,2%-100,d1=1%min:~-2%-100,d2=1%max:~-2%-100,s1=~-m1*31+d1-1,s2=(13-m2)*31-d2
- ::进行一些计算,这里的s1和s2是最重要的两个值,直接关系到后文“砍头去尾”的算法
-
- (for /l %%a in (%y2% -1 %y1%) do (
- set /a "1/(%%a%%3200)"||set pr=!pr! %%a0229
- for %%b in (%md:*13 =%) do (
- for %%c in (%md%) do (
- echo %%a%%b%%c
- )
- )
- ))>tmp 2>nul
- ::简单输出所有可能正确的日期
-
- more +%s2% tmp|sort|more +%s1%|findstr /e "[^2].. 12.. 02[0-1]. 022[0-8] [02468][048]0229 [13579][26]0229"|findstr /ve "0[2469]31 0230 1131 [02468][048]000229 [13579][26]000229 %pr%">pr.txt
- ::整个代码最关键的部分,先用more+sort砍头去尾,削除不在要求之内的日期,再用findstr双向筛选排除非法日期
-
- pause
复制代码
日期多的时候,速度相当快
作者: broly 时间: 2011-6-7 16:56
对于日期处理,用VBS的函数比较方便
DateAdd 函数
返回已添加指定时间间隔的日期。
DateAdd(interval, number, date)
作者: DAIC 时间: 2011-6-11 09:50
19# broly
初学乍练,不是很懂,帮忙写个代码吧。
作者: DAIC 时间: 2011-6-11 10:13
15楼的结果:73050行,还没有看到错误的日期。
c:\Test>timeit test.bat
Elapsed Time: 0:00:34.590
Process Time: 0:00:23.212- @echo off&setlocal enabledelayedexpansion
- set start=1810-01-01
- set end=2010-01-01
- set /a sy=%start:~,4%,sm=1%start:~5,2%%%100,sd=1%start:~8,2%%%100,ey=%end:~,4%,em=1%end:~5,2%%%100,ed=1%end:~8,2%%%100,a=31
- for %%a in (1 3 5 7 8 10 12 4 6 9 11) do (
- if %%a equ 4 set /a a-=1
- set /a _%%a=a
- )
- (for /l %%a in (%sy%,1,%ey%) do (
- set /a "_2=^!(%%a%%4)&^!(^!(%%a%%100))|^!(%%a%%400)+28"
- set /a a=1,b=12
- if "%%a" equ "%sy%" set /a a=sm
- if "%%a" equ "%ey%" set /a b=em
- for /l %%b in (!a!,1,!b!) do (
- set /a c=1,d=_%%b
- if "%%a%%b" equ "%sy%%sm%" set /a c=sd
- if "%%a%%b" equ "%ey%%em%" set /a d=ed
- for /l %%c in (!c!,1,!d!) do (
- for %%d in (%%b %%c) do set ".%%d=0%%d"&set ".%%d=!.%%d:~-2!"
- echo %%a-!.%%b!-!.%%c!
- )
- )
- ))>15.txt
复制代码
作者: Batcher 时间: 2011-6-11 11:54
18# zm900612
生成的那个tmp文件包含74772行,我等了一个多小时,还是没有执行完排除非法日期那部分,能否帮忙看看?- @echo off&setlocal enabledelayedexpansion
- set min=18100101
- set max=20100101
- for /l %%a in (31 -1 1) do (
- set tmp=0%%a
- set md=!md! !tmp:~-2!
- )
- set /a y1=%min:~0,-4%,y2=%max:~0,-4%,m1=1%min:~-4,2%-100,m2=1%max:~-4,2%-100,d1=1%min:~-2%-100,d2=1%max:~-2%-100,s1=~-m1*31+d1-1,s2=(13-m2)*31-d2
- (for /l %%a in (%y2% -1 %y1%) do (
- set /a "1/(%%a%%3200)"||set pr=!pr! %%a0229
- for %%b in (%md:*13 =%) do (
- for %%c in (%md%) do (
- echo %%a%%b%%c
- )
- )
- ))>tmp 2>nul
- more +%s2% tmp|sort|more +%s1%|findstr /e "[^2].. 12.. 02[0-1]. 022[0-8] [02468][048]0229 [13579][26]0229"|findstr /ve "0[2469]31 0230 1131 [02468][048]000229 [13579][26]000229 %pr%">a.txt
复制代码
作者: Batcher 时间: 2011-6-11 12:06
来个Perl的,200年,2秒多点。- use Date::Calc qw( Delta_Days Add_Delta_Days );
- @start = (1810,1,1);
- @stop = (2010,1,1);
- $j = Delta_Days(@start,@stop);
- for ( $i = 0; $i <= $j; $i++ )
- {
- @date = Add_Delta_Days(@start,$i);
- printf("%4d-%02d-%02d\n", @date);
- }
复制代码
作者: 我是马甲 时间: 2011-6-11 12:08
more 好像只能处理6万多行,会被卡住。可以打开a.txt查看最后一行
作者: CrLf 时间: 2011-6-11 12:56
还真是...测试了下,具体是65535行,看来只能改用for了,不过那效率...- ---------- TMP: 74772
- more处理后:
- ---------- TMP2: 65535
复制代码
作者: CrLf 时间: 2011-6-11 13:13
面对大于一百七十多年的情况,修改后是这样:- @echo off&setlocal enabledelayedexpansion
- set min=18100101
- set max=20100101
-
- for /l %%a in (31 -1 1) do (
- set tmp=0%%a
- set md=!md! !tmp:~-2!
- )
- ::先将个位数转换为0开头,避免在循环中计算
-
- set /a y1=%min:~0,-4%,y2=%max:~0,-4%,m1=1%min:~-4,2%-100,m2=1%max:~-4,2%-100,d1=1%min:~-2%-100,d2=1%max:~-2%-100,s1=~-m1*31+d1-1,s2=(13-m2)*31-d2
- ::进行一些计算,这里的s1和s2是最重要的两个值,直接关系到后文“砍头去尾”的算法
-
- (for /l %%a in (%y2% -1 %y1%) do (
- set /a "1/(%%a%%3200)"||set pr=!pr! %%a0229
- for %%b in (%md:*13 =%) do (
- for %%c in (%md%) do (
- echo %%a%%b%%c
- )
- )
- ))>tmp 2>nul
- ::简单输出所有可能正确的日期
- if %s2% gtr 0 set skip1="skip=%s2%"
- (for /f %skip1% %%a in (tmp) do echo %%a)>tmp2
- sort tmp2 >tmp
- if %s1% gtr 0 set skip2="skip=%s1%"
- (for /f %skip2% %%a in (tmp) do echo %%a)>tmp2
- findstr /e "[^2].. 12.. 02[0-1]. 022[0-8] [02468][048]0229 [13579][26]0229" tmp2|findstr /ve "0[2469]31 0230 1131 [02468][048]000229 [13579][26]000229 %pr%">pr.txt
- ::整个代码最关键的部分,先用more+sort砍头去尾,削除不在要求之内的日期,再用findstr双向筛选排除非法日期
-
- pause
复制代码
作者: DAIC 时间: 2011-6-11 13:48
26# zm900612
我希望把年月日用减号分开,应该修改哪些地方?
作者: CrLf 时间: 2011-6-11 14:05
本帖最后由 zm900612 于 2011-6-11 14:11 编辑
27# DAIC - [code]@echo off&setlocal enabledelayedexpansion
- set min=18100101
- set max=20100101
- echo %time%
-
- for /l %%a in (31 -1 1) do (
- set tmp=0%%a
- set md=!md! !tmp:~-2!
- )
- ::先将个位数转换为0开头,避免在循环中计算
-
- set /a y1=%min:~0,-4%,y2=%max:~0,-4%,m1=1%min:~-4,2%-100,m2=1%max:~-4,2%-100,d1=1%min:~-2%-100,d2=1%max:~-2%-100,s1=~-m1*31+d1-1,s2=(13-m2)*31-d2
- ::进行一些计算,这里的s1和s2是最重要的两个值,直接关系到后文“砍头去尾”的算法
-
- (for /l %%a in (%y2% -1 %y1%) do (
- set /a "1/(%%a%%3200)"||set pr=!pr! %%a0229
- for %%b in (%md:*13 =%) do (
- for %%c in (%md%) do (
- echo %%a-%%b-%%c
- )
- )
- ))>tmp 2>nul
- ::简单输出所有可能正确的日期
-
- if %s2% gtr 0 set skip1="skip=%s2%"
- (for /f %skip1% %%a in (tmp) do echo %%a)>tmp2
- sort tmp2 >tmp
- if %s1% gtr 0 set skip2="skip=%s1%"
- (for /f %skip2% %%a in (tmp) do echo %%a)>tmp2
- findstr /e "[^2]-.. 12-.. 02-[0-1]. 02-2[0-8] [02468][048]-02-29 [13579][26]-02-29" tmp2|findstr /ve "0[2469]-31 02-30 11-31 [02468][048]00-02-29 [13579][26]00-02-29 %pr%">pr.txt
- ::整个代码最关键的部分,先用more+sort砍头去尾,削除不在要求之内的日期,再用findstr双向筛选排除非法日期
-
- echo %time%
- pause
复制代码
少于17年的话,用这个更快- @echo off&setlocal enabledelayedexpansion
- set min=18100101
- set max=20100101
- echo %time%
-
- for /l %%a in (31 -1 1) do (
- set tmp=0%%a
- set md=!md! !tmp:~-2!
- )
- ::先将个位数转换为0开头,避免在循环中计算
-
- set /a y1=%min:~0,-4%,y2=%max:~0,-4%,m1=1%min:~-4,2%-100,m2=1%max:~-4,2%-100,d1=1%min:~-2%-100,d2=1%max:~-2%-100,s1=~-m1*31+d1-1,s2=(13-m2)*31-d2
- ::进行一些计算,这里的s1和s2是最重要的两个值,直接关系到后文“砍头去尾”的算法
-
- (for /l %%a in (%y2% -1 %y1%) do (
- set /a "1/(%%a%%3200)"||set pr=!pr! %%a0229
- for %%b in (%md:*13 =%) do (
- for %%c in (%md%) do (
- echo %%a-%%b-%%c
- )
- )
- ))>tmp 2>nul
- ::简单输出所有可能正确的日期
-
- more +%s2% tmp|sort|more +%s1%|findstr /e "[^2]-.. 12.. 0-2[0-1]. 02-2[0-8] [02468][048]-02-29 [13579][26]-02-29"|findstr /ve "0[2469]-31 02-30 11-31 [02468][048]00-02-29 [13579][26]00-02-29 %pr%">pr.txt
- ::整个代码最关键的部分,先用more+sort砍头去尾,削除不在要求之内的日期,再用findstr双向筛选排除非法日期
-
- echo %time%
- pause
复制代码
作者: DAIC 时间: 2011-6-11 22:11
28楼的结果:
Elapsed Time: 0:00:19.345
Process Time: 0:00:11.778- @echo off&setlocal enabledelayedexpansion
- set min=18100101
- set max=20100101
- for /l %%a in (31 -1 1) do (
- set tmp=0%%a
- set md=!md! !tmp:~-2!
- )
- set /a y1=%min:~0,-4%,y2=%max:~0,-4%,m1=1%min:~-4,2%-100,m2=1%max:~-4,2%-100,d1=1%min:~-2%-100,d2=1%max:~-2%-100,s1=~-m1*31+d1-1,s2=(13-m2)*31-d2
- (for /l %%a in (%y2% -1 %y1%) do (
- set /a "1/(%%a%%3200)"||set pr=!pr! %%a0229
- for %%b in (%md:*13 =%) do (
- for %%c in (%md%) do (
- echo %%a-%%b-%%c
- )
- )
- ))>tmp 2>nul
- if %s2% gtr 0 set skip1="skip=%s2%"
- (for /f %skip1% %%a in (tmp) do echo %%a)>tmp2
- sort tmp2 >tmp
- if %s1% gtr 0 set skip2="skip=%s1%"
- (for /f %skip2% %%a in (tmp) do echo %%a)>tmp2
- findstr /e "[^2]-.. 12-.. 02-[0-1]. 02-2[0-8] [02468][048]-02-29 [13579][26]-02-29" tmp2|findstr /ve "0[2469]-31 02-30 11-31 [02468][048]00-02-29 [13579][26]00-02-29 %pr%">28.txt
复制代码
作者: DAIC 时间: 2011-6-11 22:16
再次求助:http://bbs.bathome.net/viewthrea ... muid=38107#pid49141
这个代码看不懂,能否教一下怎么设置开始日期和结束日期?
欢迎光临 批处理之家 (http://www.bathome.net/) |
Powered by Discuz! 7.2 |