【问题标题】:Date validation in a Windows batch fileWindows 批处理文件中的日期验证
【发布时间】:2020-07-17 17:38:42
【问题描述】:

我有以下代码从用户 MM-DD-YYYY 获取日期并验证它是该格式,然后将其转换为 YYYY-MM-DD。一切正常……主要是。但是,我无法弄清楚为什么当它到达 YYYY 部分时它会停止验证。它可能缺少一些代码来检查。

:sof
GOTO :ValidDate

:: Get and validate date
:ValidDate
SET i=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
   SET /A i+=1
   SET dpm[!i!]=%%a
)

SET /P "inDate=First Contact Date (MM-DD-YYYY format): "
if "%inDate:~2,1%%inDate:~5,1%" neq "--" GOTO invalidDate
for /F "tokens=1-3 delims=-" %%a in ("%inDate%") do SET "MM=%%a" & SET "DD=%%b" & SET "YYYY=%%c"
ver > NUL
SET /A month=1%MM%-100, day=1%DD%-100, year=1%YYYY%-10000, leap=year%%4  2>NUL
if errorlevel 1 GOTO invalidDate
if not defined dpm[%month%] GOTO invalidDate
if %leap% equ 0 SET dpm[2]=29
if %day% gtr !dpm[%month%]! GOTO invalidDate
if %day% lss 1 GOTO invalidDate
ECHO.
ECHO.
GOTO :loopCompanyType

:invalidDate
ECHO Date input is invalid.  Fomat must be MM-DD-YYYY.
ECHO.
PAUSE
GOTO :sof

这是我最初拥有的月+日+年的代码,并结合但也无法验证。

:ValidateDate
ECHO.
SET /P month="Please enter First Contact Month (format must be MM)
ECHO.
IF [%month:~2%] NEQ [] echo Month format entered incorrectly.  Try again. & GOTO :ValidateDate
SET /P day="Please enter First Contact Day (format must be DD)
ECHO.
IF [%day:~2%] NEQ [] echo Day format entered incorrectly.  Try again. & GOTO :ValidateDate
SET /P year="Please enter First Contact Year (format must be YYYY)
ECHO.
IF [%month:~4%] NEQ [] echo Year format entered incorrectly.  Try again. & GOTO :ValidateDate
SET FCD=%year%-%month%-%day%
CHOICE /C YN /M "Is the First Contact Date %FCD% correct?"
IF ERRORLEVEL ==2 GOTO :ValidateDate
IF ERRORLEVEL ==1 GOTO :loopCompanyType

【问题讨论】:

  • 欢迎来到 Stack Overflow。请花2分钟tour。此外,打开Help center 并至少阅读How to Ask。然后,edit 您的问题提供minimal reproducible example。例如,我不明白 当它到达 YYYY 部分时它停止验证 断言。会发生什么?
  • 请注意-- 检查只会确认用户在这两个位置输入了这两个字符。它不会验证输入的字符数是否正确,或者非 - 字符是否都是整数。
  • 我最初的想法是,如果对您的最终用户没有太大的不便,请询问年份、月份、日期,并在使用时检查每个您对它们都有效感到满意,请根据需要自行加入。
  • @JosefZ 您可以输入 MM-DD-Y 并且它认为它是有效的。它需要验证 YYYY 是正确的格式。
  • @Compo 我确实尝试过类似这样的首字母。我最初在 2013 年得到了这个脚本。我在批处理方面不是最棒的,最近才意识到它已经坏了。我使用了上面发布的原始代码,因为它对用户的提示较少。我也永远无法得到月+日+年,然后结合起来验证正确。编辑显示我的原始代码。

标签: batch-file


【解决方案1】:

您可以输入MM-DD-Y,它接受它为有效。它需要验证YYYY的格式是否正确。

您可以按如下方式扩展“--”测试:

SET /P "inDate=First Contact Date (MM-DD-YYYY format): "
set "inDateX=%inDate%-bcde"
if "%inDateX:~2,1%%inDateX:~5,1%%inDateX:~10,1%" neq "---" GOTO invalidDate
for /F "tokens=1-3 delims=-" %%a in ("%inDate%") do (
    SET "MM=%%a"
    SET "DD=%%b"
    SET "YYYY=%%c"
)

哎呀!
还有一个笑话(在:loopCompanyType 标签上带有以下echos):

:loopCompanyType
ECHO. set  %inDate%
ECHO. comp %yyyy%-%mm%-%dd%

可能未公开的错误输入:.\SO\62959167.bat

First Contact Date (MM-DD-YYYY format): 12-31-20-0
 set  12-31-20-0
 comp 20-12-31

解决方案

利用FINDSTR 对正则表达式的支持。

编辑。根据有益 Compo 对 cmd 有毒字符的评论进行更新,例如>&|
给定完整脚本用于测试;我希望它现在几乎是防弹代码 sn-p。 :)

@ECHO OFF
SETLOCAL EnableExtensions EnableDelayedExpansion
:sof
GOTO :ValidDate

:: Get and validate date
:ValidDate
SET i=0
for %%a in (31 28 31 30 31 30 31 31 30 31 30 31) do (
   SET /A i+=1
   SET dpm[!i!]=%%a
)

SET /P "inDate=First Contact Date (MM-DD-YYYY format): "
set "inDateX=%inDate%-bcde"
if "%inDateX:~2,1%%inDateX:~5,1%%inDateX:~10,1%" neq "---" GOTO invalidDate
(call )
echo("%inDate%"|findstr "^\"[0-1][0-9]-[0-3][0-9]-[0-9][0-9][0-9][0-9]\"$">NUL
if errorlevel 1 GOTO invalidDate
for /F "tokens=1-3 delims=-" %%a in ("%inDate%") do (
    SET "MM=%%a"
    SET "DD=%%b"
    SET "YYYY=%%c"
)
ver > NUL
SET /A month=1%MM%-100, day=1%DD%-100, year=1%YYYY%-10000, leap=year%%4  2>NUL
if errorlevel 1 GOTO invalidDate
if not defined dpm[%month%] GOTO invalidDate
if %leap% equ 0 SET dpm[2]=29
if %day% gtr !dpm[%month%]! GOTO invalidDate
if %day% lss 1 GOTO invalidDate
GOTO :loopCompanyType

:invalidDate
ECHO "%inDate%" Date input is invalid.  Format must be MM-DD-YYYY.
ECHO.
REM PAUSE
GOTO :sof

:loopCompanyType
ECHO. set  %inDate%
ECHO. comp %yyyy%-%mm%-%dd%

输出.\SO\62959167.bat

First Contact Date (MM-DD-YYYY format): 12-19-9¹³9
"12-19-9¹³9" Date input is invalid.  Fomat must be MM-DD-YYYY.

First Contact Date (MM-DD-YYYY format): 12-19-9<&9
"12-19-9<&9" Date input is invalid.  Fomat must be MM-DD-YYYY.

First Contact Date (MM-DD-YYYY format): 12-19-9139
 set  12-19-9139
 comp 9139-12-19

注意Dave Benham's reply to setting ERRORLEVEL to 0 questionver&gt;NUL 的替代品):

如果你想强制errorlevel为0,那么你可以使用这个 完全不直观,但非常有效的语法:(call )。空间 call 之后很关键。如果要将错误级别设置为 1,则 可以使用(call)。重要的是后面没有任何空间 打电话

顺便说一句,有些年份可以被 4 整除,而不是 leap years...

【讨论】:

  • 如果最终用户要输入 19-39-9¹³9 作为他们的日期,则使用基于 findstr 的新解决方案将通过有效。更不用说如果他们输入&amp;| 会发生什么。我还将假设虽然使用 &gt;&lt; 字符可能不会作为有效日期传递,但它可能会尝试写入文件和/或生成错误。
  • @Compo findstr 保护cmd 特殊字符除了双引号...用户输入12-19-19"9(或类似的)抛出命令的语法是不正确的。(可接受的风险?)
  • 非常感谢@JosefZ 和@Compo !!!现在可以根据需要完美运行。
【解决方案2】:

这是一个使用我在 cmets 中提出的建议的示例。

要求最终用户输入年份,然后是月份,然后是日期,每个都经过验证,并且只有在所有内容都正确输入后,代码才会继续。我已经做到了,所以最终用户输入的内容并不重要,(可能除了一些奇怪的 CTRL-? 序列).

@Echo Off
SetLocal EnableExtensions DisableDelayedExpansion

:AskYear
ClS
Set "YYYY="
Set /P "YYYY=Please enter a four digit year from 1970 to 2020 incl e.g. 2016 >"
Set YYYY 2>NUL|%__AppDir__%findstr.exe^
 /R "^YYYY=19[789][0123456789]$ ^YYYY=20[01][0123456789]$ ^YYYY=2020$">NUL^
 ||GoTo AskYear

:AskMonth
ClS
Set "MM="
Set /P "MM=Please enter a two digit month e.g. 04 >"
Set MM 2>NUL|%__AppDir__%findstr.exe /R "^MM=0[123456789]$ ^MM=1[012]$">NUL^
 ||GoTo AskMonth

:GetDays
Set "DM=^DD=0[123456789]$ ^DD=[12][0123456789]$ ^DD=3[01]$"
For %%G In (04 06 09 11
)Do If "%%G" == "%MM%" Set "DM=^DD=0[123456789]$ ^DD=[12][0123456789]$ ^DD=30$"
If "%MM%" == "02" (Set "DM=^DD=0[123456789]$ ^DD=[12][012345678]$ ^DD=19$"
    SetLocal EnableDelayedExpansion&Set /A $=YYYY%%4
    If "!$!" == "0" (EndLocal&Set "DM=^DD=0[123456789]$ ^DD=[12][0123456789]$"
    )Else EndLocal)

:AskDay
ClS
Set "DD="
Set /P "DD=Please enter a two digit day e.g. 08 >"
Set DD 2>NUL|%__AppDir__%findstr.exe /R "%DM%">NUL||GoTo AskDay

Echo(%YYYY%-%MM%-%DD% is a valid date&Pause

显然,最后一行只是确认输入了有效日期,并将其放在一起显示。您可以将其更改为您自己的代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    • 2012-12-13
    • 1970-01-01
    相关资源
    最近更新 更多