午夜后时间设置不正确

编程入门 行业动态 更新时间:2024-10-28 02:22:34
本文介绍了午夜后时间设置不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我正在使用以下方法将日期/时间设置为更具可读性:

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]

午夜之后时间格式如何从HH:MM:SS:MS更改为H:MM:SS:MS并弄乱格式 并且当它包含:时,由于字符被移了一个,所以当我用它制作日志文件时,它是不正确的.

他们有什么办法强迫它始终是一种格式?

解决方案

对动态环境变量DATE和TIME进行字符串替换的用法,如我对问题%date是什么:〜-4,4 %% date:〜-10,2 %% date:〜-7,2%_%time:〜0, 2 %% time:〜3,2%平均值?非常快,但缺点是日期和时间字符串的格式取决于为运行批处理文件所使用的帐户配置的地区(国家/地区)

该日期可以在开始时不带或带有缩写的工作日,并且可以在不带字母或缩写的工作日之后添加逗号.日期字符串的格式可以为年/月/日或月/日/年或日/月/年,并带有/或.或-或 作为分隔符.另请参阅Wikipedia文章,有关国家/地区的日期格式.

时间可以是12或24小时格式.小时可以小于或小于10.

未发布在运行echo %DATE% %TIME%的上午10点之前和下午3点之前的输出信息,以了解本地日期/时间格式.

似乎可以将以下代码与:用作时间字符串中的分隔符:

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%]"

:或.或 剩余的小时数以前导零分配给环境变量Hour. :或.或 的分钟权分配给变量Minute.日期/时间字符串是通过仅使用Hour的最后两位数字来构造的,以使小时最终始终是将日期/时间字符串中的两位数字分配给环境变量bdate.

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

可以使用 Windows管理来获取与区域无关的日期/时间字符串. Instrumentation Command 线路工具 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==.来获取分配给循环变量I的值的原因20200208124514的原因在环境变量DateTime旁边分配.

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

当然可以在任何地方使用bdate而不是DateTime来仅使用一个环境变量而不是两个变量.

使用 WMIC 来获取本地日期/时间的优点是它独立于Windows区域设置,甚至在Windows XP上也可以使用.缺点是与使用 DATE 和 TIME 环境变量的用法相比,命令执行要花费相当长的时间(一到两秒)微秒.

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

通常这是一个问题,因为set "EnvironmentVariable=%%I"的结果是%%I扩展为正回车,因此删除之前已经定义的具有正确值的环境变量.

有多种解决方案可解决命令 FOR 的Unicode解析错误.一旦将值分配给环境变量,就可以追加& goto Label并跳到 FOR 循环下的:Label退出循环,从而完全避免出现此问题.

另一种解决方案是将if not defined DateTime set "DateTime=%%I"与 FOR 命令行上方的set "DateTime="结合使用,以确保命令 SET 仅执行一次.

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

请参见如何在解析输出时更正变量覆盖行为?和 cmd会以某种方式写中文文本作为输出,以获取有关在UTF-16 LE编码输出上解析 FOR 问题的详细信息.

另一种获得当前日期和时间区域独立性的解决方案是使用 ROBOCOPY ,该版本自Windows Vista和Windows Server 2003以来在Windows的系统目录中可用,但默认情况下在Windows XP中不可用.可以将Windows Server 2003的robocopy.exe复制到Windows XP的%SystemRoot%\System32,以在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=/: " %%I in ('%SystemRoot%\System32\robocopy.exe "%SystemDrive%\|" . /NJH') do if not defined bdate set "bdate=[%%K-%%J-%%I]-[%%L-%%M]"

在这种情况下,

FOR 在后台以%ComSpec% /c启动另一个命令过程,并且将两个'之间的命令行附加为附加参数,这导致Windows安装在C:\Windows中执行:

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

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

  • I ...年
  • J ...月
  • K ...天
  • L ...小时
  • M ...分钟

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

但是 FOR 将在第二条错误消息行中再次运行命令 SET .因此,在运行 FOR 之前,环境变量bdate是显式未定义的.环境变量bdate首先用日期/时间字符串定义,然后由于附加的 IF 条件而在 FOR 处理第二个非空行时不再进行修改避免用不需要的字符串覆盖感兴趣的日期/时间字符串.

与 WMIC 解决方案相比, ROBOCOPY 解决方案的优点是执行时间更快.

要了解所使用的命令及其工作方式,请打开命令提示符窗口,然后在此处执行以下命令,并非常仔细地阅读每个命令显示的所有帮助页面.

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

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

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

i am using the following to set the date/time to something more readable:

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%]

this works well and outputs something like : [02-06-2020]-[22-59]

How ever after midnight the time format changes from HH:MM:SS:MS to H:MM:SS:MS and messes up the format and when it includes the : in the time, since the characters are shifted over by one, when i make the log file with that it is incorrect.

Is their any way to force it to always be one format?

解决方案

The usage of the dynamic environment variables DATE and TIME with string substitutions as explained very detailed by my answer on the question What does %date:~-4,4%%date:~-10,2%%date:~-7,2%_%time:~0,2%%time:~3,2% mean? is very fast, but has the disadvantage that the format of the date and the time string depends on region (country) configured for the account used on running the batch file.

The date can be without or with abbreviated weekday at beginning and without or with a comma appended after abbreviated weekday. The date string can be in the format year/month/day or month/day/year or day/month/year with / or . or - or   as separator. See also the Wikipedia article about date format by country.

The time can be in 12 or 24 hour format. The hour can be without or with a leading 0 on being less than 10.

It was not posted what is output on running echo %DATE% %TIME% before ten o'clock in the morning and at three o'clock in the afternoon to know the local date/time format.

It looks like it is possible to use the following code with : as separator in time string:

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%]" )

If the second character in time string is a colon, the condition is true and the first expression is used with 0 added left to single digit hour, otherwise the ELSE block is used with the two digit hour.

Another solution with separator in time string being either a colon or a dot or a space would be:

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%]"

The hour left to : or . or   is assigned to environment variable Hour with a leading zero. The minute right to : or . or   is assigned to variable Minute. The date/time string is built with taking only the last two digits of Hour to have the hour finally always with two digits in date/time string assigned to environment variable bdate.


Much better would be getting current date and time region (country) independent and reformat them to wanted format using string substitutions.

A region independent date/time string can be get using Windows Management Instrumentation Command line tool WMIC.

The command line

wmic OS GET LocalDateTime /VALUE

outputs UTF-16 Little Endian encoded for example:

LocalDateTime=20200208124514.468000+060

There are two empty lines, then the line with the current local date/time in format yyyyMMddHHmmss.microsecond±UTC offset in minutes and two more empty lines.

These data can be used with a batch code like this:

@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%]"

Of interest is here only the date/time string between the equal sign and the decimal point which is the reason for using for /F options tokens=2 delims==. to get just 20200208124514 assigned to loop variable I of which value is assigned next to environment variable DateTime.

The environment variable DateTime is reformatted using string substitutions to get the date/time string in format [dd-MM-yyyy]-[HH-mm] resulting in environment variable bdate being defined with [08-02-2020]-[12-45].

It would be of course possible to use bdate everywhere instead of DateTime to use just one environment variable instead of two variables.

The advantage of using WMIC to get local date/time is its independence on Windows region settings and that it is working even on Windows XP. The disadvantage is that the command execution takes a quite long time (one to two seconds) in comparison to the usage of the DATE and TIME environment variables which are accessed in a few microseconds.

The command FOR has problems parsing UTF-16 LE encoded Unicode output correct. It interprets the byte sequence 0D 00 0A 00 (carriage return + line-feed) of the WMIC output wrong as 0D 0D 0A, i.e. as two carriage returns and one line-feed. This results in interpreting the last two empty lines at end of WMIC output as two lines with a single carriage return as string.

That is very often a problem because the result of set "EnvironmentVariable=%%I" is with %%I expanding to just carriage return the deletion of the environment variable already defined before with the correct value.

There are multiple solutions to work around this Unicode parsing error of command FOR. It is possible to append & goto Label to exit the loop with a jump to :Label below the FOR loop once the value is assigned to the environment variable to avoid running into this problem at all.

Another solution is using if not defined DateTime set "DateTime=%%I" with set "DateTime=" above the FOR command line to make sure the command SET is executed only once.

One more solution is the one used in this code. The name of the property and its value are output on same line because of using WMIC option /VALUE. The command FOR runs the command SET because of tokens=2 only when it could split up the current line into at least two substrings (tokens) using equal sign and dot as delimiters because of delims==.. But the wrong parsed empty lines of WMIC output are for FOR just lines containing only a carriage return and therefore has no second token. For that reason the wrongly parsed empty lines are also ignored here by the command FOR.

See How to correct variable overwriting misbehavior when parsing output? and cmd is somehow writing Chinese text as output for details on parsing problem of FOR on UTF-16 LE encoded output.


Another solution to get current date and time region independent is using ROBOCOPY which is available since Windows Vista and Windows Server 2003 in system directory of Windows, but is by default not available on Windows XP. robocopy.exe of Windows Server 2003 can be copied to %SystemRoot%\System32 of Windows XP to use this executable also on Windows XP, but it is not available by default on Windows XP.

ROBOCOPY is executed with invalid source directory string "C:\|" and valid destination directory string . (could be also something other valid) and argument /NJH to suppress the output of the header information.

robocopy "C:\|" . /NJH

This execution produces the error message:

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

The format of current date/time at beginning of second line after the empty line is region independent.

This output can be processed with:

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

FOR starts in this case one more command process in background with %ComSpec% /c and the command line between the two ' appended as additional arguments which results in Windows being installed into C:\Windows in the execution of:

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

The first five slash or colon or space separated strings of the first non-empty line of the error message output to handle STDOUT of the background command process captured by FOR are assigned to:

  • I ... year
  • J ... month
  • K ... day
  • L ... hour
  • M ... minute

The five data strings are concatenated to the date/time string in the wanted format.

But FOR would run the command SET once again for the second error message line. For that reason the environment variable bdate is explicitly undefined before running FOR. The environment variable bdate is defined first with the date/time string and is next not modified anymore on FOR processing the second non-empty line because of the additional IF condition to avoid overwriting the date/time string of interest with an unwanted string.

The advantage of the ROBOCOPY solution in comparison to the WMIC solution is its much faster execution time.


For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

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

PS: There are lots of other solutions to get current date/time in a specific format independent on country configured for the used account. All those alternative solutions can be found in the answers on:

How do I get current date/time on the Windows command line in a suitable format for usage in a file/folder name?

更多推荐

午夜后时间设置不正确

本文发布于:2023-11-24 04:03:35,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1623902.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:不正确   午夜   时间

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!