午夜后时间设置不正确

2024-05-10

我使用以下命令以更易读的格式获取当前日期/时间:

set day=%date:~4,2%
set mth=%date:~7,2%
set yr=%date:~10,4%
set hur=%time:~0,2%
set min=%time:~3,2%
set bdate=[%day%-%mth%-%yr%]-[%hur%-%min%]

这效果很好,输出如下:[02-06-2020]-[22-59]

但是,午夜过后,时间格式会更改为时:分:SS:女士 to 时:分:SS:女士。这会弄乱格式,因为它包含冒号:时间上因为人物移动了一位。这会导致午夜后创建的日志文件中出现无用的日期/时间信息。

有没有办法让时间始终采用两位数小时的格式?


动态变量 DATE 和 TIME 的使用

动态变量的使用DATE and TIME正如我对问题的回答非常详细地解释的那样,使用字符串替换%date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% 是什么意思? https://stackoverflow.com/a/37236739/3074564速度非常快,但缺点是日期和时间字符串的格式取决于为运行批处理文件所使用的帐户配置的区域(国家/地区)。

日期开头可以不带或带缩写工作日,并且在缩写工作日后不带或带逗号。日期字符串可以采用以下格式年月日 or 月日年 or 日月年 with / or . or - or  作为分隔符。另请参阅维基百科文章:按国家/地区划分的日期格式 https://en.wikipedia.org/wiki/Date_format_by_country.

时间可以采用 12 或 24 小时格式。小时可以不带或带前导0小于 10 时。

没有发布运行时的输出是什么echo %DATE% %TIME%上午十点前和下午三点前了解当地日期/时间格式。

看起来可以使用以下代码:作为时间字符串中的分隔符:

if "%TIME:~1,1%" == ":" (
    set "bdate=[%DATE:~-10,2%-%DATE:~-7,2%-%DATE:~-4%]-[0%TIME:~0,1%-%TIME:~2,2%]"
) else (
    set "bdate=[%DATE:~-10,2%-%DATE:~-7,2%-%DATE:~-4%]-[%TIME:~0,2%-%TIME:~3,2%]"
)

如果时间字符串中的第二个字符是冒号,则条件为 true,并且第一个表达式与0向左添加一位数小时,否则ELSE块与两位数小时一起使用。

时间字符串中的分隔符是冒号、点或空格的另一个解决方案是:

for /F "tokens=1,2 delims=:. " %%I in ("%TIME%") do set "Hour=0%%I" & set "Minute=%%J"
set "bdate=[%DATE:~-10,2%-%DATE:~-7,2%-%DATE:~-4%]-[%Hour:~-2%-%Minute%]"

还剩一小时: or . or  分配给环境变量Hour带有前导零。右边的分钟: or . or  被分配给变量Minute。日期/时间字符串仅采用最后两位数字构建Hour让小时最终始终以日期/时间字符串中的两位数字分配给环境变量bdate.


使用 WMIC 获取当前日期/时间

更好的方法是使当前日期和时间区域(国家)独立并使用字符串替换将其重新格式化为所需的格式。

可以使用获取与区域无关的日期/时间字符串Windows 管理规范命令 https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmic直线工具WMIC.

命令行

wmic OS GET LocalDateTime /VALUE

输出 UTF-16 Little Endian 编码,例如:



LocalDateTime=20200208124514.468000+060


有两行空行,然后是格式为当前本地日期/时间的行yyyyMMddHHmmss.microsecond±UTC 偏移量(以分钟为单位)还有两个空行。

该数据可以与如下批处理代码一起使用:

@echo off
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "DateTime=%%I"
set "bdate=[%DateTime:~6,2%-%DateTime:~4,2%-%DateTime:~0,4%]-[%DateTime:~8,2%-%DateTime:~10,2%]"

有趣的是这里只有等号和小数点之间的日期/时间字符串,这就是使用的原因for /F选项tokens=2 delims==.得到公正20200208124514分配给循环变量I其中的值被分配到环境变量旁边DateTime.

环境变量DateTime使用字符串替换重新格式化以获取格式为的日期/时间字符串[dd-MM-yyyy]-[HH-mm]导致环境变量bdate被定义为[08-02-2020]-[12-45].

当然可以使用bdate到处而不是DateTime仅使用一个环境变量而不是两个变量。

使用的优点WMIC获取本地日期/时间的原因是它独立于 Windows 区域设置,并且甚至可以在 Windows XP 上运行。缺点是与使用DATE and TIMEWindows 命令处理器的动态变量,可在几微秒内访问。

命令FOR正确解析 UTF-16 LE 编码的 Unicode 输出时出现问题。它解释字节序列0D 00 0A 00(回车+换行)WMIC输出错误为0D 0D 0A,即两个回车和一个换行。这会导致解释末尾的最后两个空行WMIC输出为两行,单个回车符作为字符串。

这通常是一个问题,因为结果set "EnvironmentVariable=%%I"是与%%I扩展为仅回车,删除之前已使用正确值定义的环境变量。

有多种解决方案可以解决命令的 Unicode 解析错误FOR。可以追加& goto Label跳转到退出循环:Label以下FOR将值分配给环境变量后循环,以避免遇到此问题。

另一种解决方案是使用if not defined DateTime set "DateTime=%%I" with set "DateTime="上面FOR命令行以确保命令SET仅执行一次。

另一种解决方案是此代码中使用的解决方案。由于使用了属性的名称及其值在同一行输出WMIC option /VALUE。命令FOR运行命令SET因为tokens=2仅当它可以使用等号和点作为分隔符将当前行分成至少两个子字符串(标记)时,因为delims==.。但是错误地解析了空行WMIC输出是为了FOR只是一行仅包含回车符,因此没有第二个标记。因此,命令也会忽略错误解析的空行FOR.

See 解析输出时如何纠正变量覆盖错误行为? https://stackoverflow.com/a/24965431/3074564 and cmd 以某种方式写入中文文本作为输出 https://stackoverflow.com/questions/10210553/有关解析问题的详细信息FOR在 UTF-16 Little Endian 编码输出上。


使用 ROBOCOPY 获取当前日期/时间

获得当前日期和时间区域独立的另一种解决方案是使用ROBOCOPY从 Windows Vista 和 Windows Server 2003 开始​​,它在 Windows 的系统目录中可用,但默认情况下在 Windows XP 上不可用。robocopy.exeWindows Server 2003 的文件可以复制到%SystemRoot%\System32Windows XP 也可以在 Windows XP 上使用此可执行文件,但默认情况下它在 Windows XP 上不可用。

ROBOCOPY使用无效的源目录字符串执行"C:\|"和有效的目标目录字符串.(也可能是其他有效的东西)和论证/NJH抑制头信息的输出。

robocopy "C:\|" . /NJH

此执行会产生错误消息:


2020/02/08 12:45:14 ERROR 123 (0x0000007B) Accessing Source Directory C:\|\
The filename, directory name, or volume label syntax is incorrect.

空行后第二行开头的当前日期/时间的格式与区域无关。

该输出可以通过以下方式处理:

set "bdate="
for /F "tokens=1-5 delims=/: " %%G in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do if not defined bdate set "bdate=[%%I-%%H-%%G]-[%%J-%%K]"

FOR在这种情况下,在后台启动另一个命令进程%ComSpec% /c以及两者之间的命令行'作为附加参数附加,导致 Windows 安装到C:\Windows在执行中:

C:\Windows\System32\cmd.exe /c C:\Windows\System32\robocopy.exe "C:\|" . /NJH

要处理的错误消息输出的第一个非空行的前五个斜杠、冒号或空格分隔的字符串STDOUT捕获的后台命令进程FOR被分配给:

  • G... 年
  • H... 月
  • I ... day
  • J... 小时
  • K... 分钟

五个数据字符串以所需格式连接到日期/时间字符串。

But FOR会运行命令SET再次查看第二个错误消息行。因此环境变量bdate在运行之前明确未定义FOR。环境变量bdate首先使用日期/时间字符串定义,然后不再修改FOR由于附加的原因,处理第二个非空行IF条件以避免用不需要的字符串覆盖感兴趣的日期/时间字符串。

的优点ROBOCOPY解决方案相比WMIC解决方案是其更快的执行时间。


附加信息

要了解所使用的命令及其工作原理,请打开命令提示符 https://www.howtogeek.com/235101/10-ways-to-open-the-command-prompt-in-windows-10/窗口中,执行以下命令,并完整、仔细地阅读每个命令显示的帮助页面。

  • echo /?
  • for /?
  • if /?
  • robocopy /?
  • set /?
  • wmic /?
  • wmic os /?
  • wmic os get /?
  • wmic os get localdatetime /?

PS:还有许多其他解决方案可以以特定格式获取当前日期/时间,与为所用帐户配置的国家/地区无关。所有这些替代解决方案都可以在以下答案中找到:

如何在 Windows 命令行上以合适的格式获取当前日期/时间以在文件/文件夹名称中使用? https://stackoverflow.com/questions/203090

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

午夜后时间设置不正确 的相关文章

随机推荐