Использование динамических c переменных среды DATE
и TIME
со строковыми подстановками, как очень подробно объяснил мой ответ на вопрос Что означает% date: ~ -4,4 %% date: ~ -10,2 %% дата: ~ -7,2% _% время: ~ 0,2 %% время: ~ 3,2% значит? очень быстро, но имеет тот недостаток, что формат дата и строка времени зависят от региона (страны), настроенного для учетной записи, используемой для запуска пакетного файла.
Дата может быть без или с сокращенным днем недели в начале и без или с запятой, добавленной после сокращенного дня недели. Строка даты может иметь формат год / месяц / день или месяц / день / год или день / месяц / год с /
или .
или -
или
в качестве разделителя. См. Также статью в Википедии о формате даты по стране .
Время может быть в формате 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%]"
)
Если второй символ в строке времени - это двоеточие, условие истинно, и первое выражение используется с добавлением 0
слева к одиночному ди git часу, в противном случае блок ELSE используется с двумя ди git час.
Другое решение с разделителем в строке времени, являющемся либо двоеточием, либо точкой, либо пробелом, будет:
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 Команда инструментария управления линейный инструмент WMI C.
Командная строка
wmic OS GET LocalDateTime /VALUE
выводит кодировку UTF-16 Little Endian, например:
LocalDateTime=20200208124514.468000+060
Есть две пустые строки, затем строка с текущей локальной датой / временем в формате ггггMMddHHmmss.microsecond ± UT C смещение в минутах и еще две пустые строки.
Эти данные могут использоваться с кодом партии, подобным этому:
@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
options tokens=2 delims==.
чтобы получить только 20200208124514
для l oop переменную I
, значение которой присваивается рядом с переменной окружения DateTime
.
Переменная среды DateTime
переформатируется использование подстановок строк для получения строки даты / времени в формате [dd-MM-yyyy]-[HH-mm]
, в результате чего переменная окружения bdate
определяется с помощью [08-02-2020]-[12-45]
.
Конечно, можно было бы использовать bdate
везде вместо DateTime
для использования только одной переменной среды вместо двух.
Преимущество использования WMI C для получения локальной даты / времени заключается в ее независимости от Windows настроек региона и рабочих даже на Windows XP. Недостатком является то, что выполнение команды занимает довольно много времени (от 1 до 2 секунд) по сравнению с использованием переменных окружения DATE и TIME , доступ к которым осуществляется за несколько микросекунд.
Команда FOR имеет проблемы с синтаксическим анализом вывода Unicode правильно. Он интерпретирует последовательность байтов 0D 00 0A 00 0D 00 0A 00 в конце вывода WMI C из-за двух пустых строк как 0D 0D 0A, то есть как два возврата каретки и один перевод строки. Это приводит к интерпретации двух последних пустых строк в конце вывода WMI C в виде одной строки с одиночным возвратом каретки в виде строки.
Это очень часто проблема, потому что результат set "EnvironmentVariable=%%I"
означает %%I
с расширением до простого возврата каретки и удаления переменной среды, уже определенной ранее с правильным значением.
Существует несколько решений для устранения этой ошибки синтаксического анализа Unicode команды ДЛЯ . Можно добавить & goto Label
для выхода из l oop с переходом на :Label
ниже FOR l oop, как только значение будет присвоено переменной среды, чтобы избежать этой проблемы вообще.
Другое решение - использовать if not defined DateTime set "DateTime=%%I"
с явным set "DateTime="
над командной строкой FOR , чтобы команда SET выполнялась только один раз.
Еще одно решение используется в этом коде. Имя свойства и его значение выводятся в одной строке из-за использования WMI C option /VALUE
. Команда FOR запускает команду SET из-за tokens=2
только тогда, когда она может разбить текущую строку как минимум на две подстроки (токены), используя знак равенства и точку в качестве разделителей из-за delims==.
. Но неверный анализируемый конец вывода WMI C предназначен для FOR строки, содержащей только возврат каретки и, следовательно, не имеет второго токена. По этой причине неправильно проанализированные пустые строки здесь также игнорируются командой FOR .
См. Как исправить неправильное поведение при перезаписи переменных при разборе вывода? и cmd каким-то образом пишет китайский текст в качестве вывода для получения подробной информации о проблеме синтаксического анализа FOR в кодированном выводе UTF-16 LE.
Другое решение для получения текущей даты и региона времени независимо использует ROBOCOPY , который доступен с Windows Vista и Windows Server 2003 в системном каталоге Windows, но по умолчанию недоступен на Windows XP. robocopy.exe
из Windows Server 2003 можно скопировать в %SystemRoot%\System32
из Windows 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.
Формат текущей даты / времени в начале второй строки после пустой строки не зависит от региона.
This вывод может быть обработан с помощью:
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
Первые пять строк sla sh или двоеточия или разделенных пробелами первой непустой строки t Вывод сообщения об ошибке для обработки STDOUT фонового командного процесса, захваченного FOR , присваивается
I
... year J
... месяц K
... день L
... час M
... минута
Пять строк данных объединяются со строкой даты / времени в требуемом формате.
Но FOR будет запускать команду SET один раз снова для второй строки сообщения об ошибке. По этой причине переменная окружения bdate
явно не определена перед запуском FOR . Переменная среды bdate
определяется сначала со строкой даты / времени и больше не изменяется при FOR , обрабатывающей вторую непустую строку из-за дополнительного условия IF , чтобы избежать перезаписи интересующая строка даты / времени с нежелательной строкой.
Преимущество решения ROBOCOPY по сравнению с решением WMI C заключается в гораздо более быстром времени выполнения.
Для понимания используемых Команды и как они работают, откройте окно командной строки , выполните там следующие команды и полностью прочитайте все страницы справки, отображаемые для каждой команды.
echo /?
for /?
if /?
robocopy /?
set /?
wmic /?
wmic os /?
wmic os get /?
wmic os get localdatetime /?
PS: существует множество других решений для получения текущей даты / времени в заданном c Формат не зависит от страны, настроенной для используемой учетной записи. Все эти альтернативные решения можно найти в ответах:
Как получить текущую дату / время в командной строке Windows в подходящем формате для использования в имени файла / папки?