【问题标题】:Calculate business days using a batch file使用批处理文件计算工作日
【发布时间】:2013-03-01 14:04:10
【问题描述】:

我正在尝试编写一个非常简单的批处理文件。

如果今天是 03/13,我希望我的批处理文件输出:

“我会在 03/15 给你回电话”

因此需要日期并添加 2 个工作日。所以如果是 03/15:

“我会在 03/19 给你回电话”

【问题讨论】:

  • 只是一个友好的建议:不要对批处理文件执行此操作。日期数学和操作在那里几乎是不可能的,需要非常小心和大量的代码。
  • 有没有办法在excel中做到这一点,然后让批处理文件调用输出?

标签: date batch-file command


【解决方案1】:

嗯,不用担心,可以批量完成。 :) 这是我的一个实现(大约 150 行代码)。

示例

https://gist.github.com/DavidRuhmann/4666270

用法

做这样的事情来适应周末。

if "%Date:~0,3%"=="Thu" call :DaysAhead 4
if "%Date:~0,3%"=="Fri" call :DaysAhead 4
if "%Date:~0,3%"=="Sat" call :DaysAhead 3
if "%Date:~0,3%"=="Sun" call :DaysAhead 2
if "%Date:~0,3%"=="Mon" call :DaysAhead 2
if "%Date:~0,3%"=="Tue" call :DaysAhead 2
if "%Date:~0,3%"=="Wed" call :DaysAhead 2

【讨论】:

  • 其他区域设置失败。这正是我在批处理文件中很难正确处理日期的意思。您应该改为从 WMI 获取日期。然后是 set /a 在 0 填充值上的问题,目前工作正常,但要等到 2013 年 4 月 9 日才能看到它崩溃。
  • @Joey - 这正是我说它可以完成的原因,这里是一个实现。我编写了我的脚本,以便可以轻松调整它。要求仅更改 7 个%Date% 调用以支持不同的格式。此外,修复了set /a 问题。 :)
  • 注意:我推荐使用 rojo 的 JScript 批处理混合答案,除非您需要纯批处理解决方案。
【解决方案2】:

使用 JScript 来计算日期,你就成功了。

@if (@X)==(@Y) @end /* (batch + jscript hybrid script init)

:: *** Batch script *****

@echo off
setlocal
for /f %%I in ('cscript /nologo /e:jscript "%~f0"') do (
    echo I will call you back on %%I
)

goto :EOF

:: *** JScript script *****/
var dow = new Date().getDay();
var days = (dow > 4) ? 9 - dow : (dow == 4 ? 4 : 2);
var d = new Date(new Date().getTime() + (1000 * 60 * 60 * 24) * days);
WScript.echo((d.getMonth() + 1) + '/' + d.getDate());

如果今天是星期四,脚本将返回下一个星期一。周五至周日,下周二。周一到周三,提前两天。而且您不必担心语言环境、闰年、闰年、农历周期等。

【讨论】:

  • 哈!我喜欢这种混合批处理和 jscript 的非常原始的方式。我以前没见过。 +1 :-)
  • @NateHekman - :) 我不能完全相信它。 dbenham 是这类东西的大师。我首先从他那里得到了这个想法。查看他的repl.bat 脚本。这是一个混合批处理 + jscript 脚本,其工作方式类似于sed。真是令人印象深刻。
  • @rojo:我可以为您的 Batch-JScript 混合脚本建议一种不同的格式吗? stackoverflow.com/questions/15167742/… 在我看来,这种格式更清晰(你的方法可能会让那些不知道 */ 结束 Batch 部分并开始 JScript 代码的人感到困惑)。
  • @JB - 如果您同意这样做是合适的,请考虑 accepting my answer formally。谢谢!
【解决方案3】:

下面的批处理文件做你想做的事:

@echo off
rem AddBusinessDays.bat date numOfDays
rem Antonio Perez Ayala

rem Convert the date to Julian Day Number + number of days
for /F "tokens=1-3 delims=/" %%a in ("%1") do (
   set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
set /A a=mm-14, jd=(1461*(yy+4800+a/12))/4+(367*(mm-2-12*(a/12)))/12-(3*((yy+4900+a/12)/100))/4+dd-32075+2+%2, dow=jd%%7

rem Adjust Julian Day Number to avoid weekends
if %dow% lss 2 set /A jd+=2-dow

rem Convert Julian Day Number back to date
set /A l=jd+68569-2,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l

rem Assemble the result
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
set newDate=%mm%/%dd%/%yy%
echo %newDate%

参考:http://www.hermetic.ch/cal_stud/jdn.htm#comp

例如:

>echo %date%
03/13/2013

>AddBusinessDays.bat %date% 2
03/15/2013

>AddBusinessDays.bat %date% 3
03/18/2013

>AddBusinessDays.bat %date% 4
03/18/2013

>AddBusinessDays.bat %date% 5
03/18/2013

>AddBusinessDays.bat %date% 6
03/19/2013

安东尼奥

PS - 是的,我知道这种方法不适用于世界上的每个人。好消息是我不是为他们所有人编写了这个解决方案,而是为 OP 编写了这个解决方案,尽管很容易为每台计算机修改它。例如,由于我的语言环境是 DD/MM/YYYY,以前的程序在我的计算机上运行 NOT,但是我可以在前面的程序的两行中交换 ddmm,我很确定这个世界上大多数人也有能力做到这一点! ;-)

嗨,安东尼奥, 就在今天,我发现你分享的代码提前 7 天以上都没有工作,我改变了一些东西,现在它可以工作了。

@echo off
rem AddBusinessDays.bat date numOfDays
rem adapted by Leonardo Contreras based on Antonio Perez Ayala with handling for more than 7 days

rem to convert Dow mm/dd/yyyy to mm/dd/yy
set mydate=%date:~4,2%/%date:~7,2%/%date:~10,4%

rem Convert the date to Julian Day Number + number of days
for /F "tokens=1-3 delims=/" %%a in ("%mydate%") do (
   set /A mm=10%%a %% 100, dd=10%%b %% 100, yy=%%c
)
rem dow_orig is based on a 0-6 days statrting on Monday
set /A a=mm-14, jd_orig = (1461*(yy+4800+a/12))/4+(367*(mm-2-12*(a/12)))/12-(3*((yy+4900+a/12)/100))/4+dd-32075, dow_orig=jd_orig%%7

rem calculate new julian's day
set /A numw = (dow_orig+%3)/5, njd = jd_orig+%3+numw*2, dow=(njd)%%7 

rem Adjust Julian Day Number to avoid weekends
if %dow% gtr 5 (set /A jd+=2 )

rem Convert Julian Day Number back to date
set /A l=njd+68569,n=(4*l)/146097,l=l-(146097*n+3)/4,i=(4000*(l+1))/1461001,l=l-(1461*i)/4+31,j=(80*l)/2447,dd=l-(2447*j)/80,l=j/11,mm=j+2-(12*l),yy=100*(n-49)+i+l

rem Assemble the result
if %dd% lss 10 set dd=0%dd%
if %mm% lss 10 set mm=0%mm%
set newDate=%mm%/%dd%/%yy%
echo %newDate%

【讨论】:

  • :O 您可以在一个set /a 调用中放置多个分配吗?我从未注意到帮助文本中的表达式分隔符。
猜你喜欢
  • 1970-01-01
  • 2019-04-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-15
  • 2013-09-08
  • 2012-04-12
相关资源
最近更新 更多