1 (изменено: Rumata, 2010-01-22 19:42:40)

Тема: CMD/BAT: работа с датой и временем в командной строке

Эта тема родилась почти два года назад. Нам потребовалось самыми простыми средствами ТОЛЬКО командной строки получит временной слепок в формате ГГГГММДД_ччммсс (Год, Месяц, День, часы, минуты, секунды). В дальнейшем этот слепок предполагалось использовать в именах файлов для предотвращения путаницы в создаваемых однотипных файлах. Решение было найдено и использовалось некоторое время (решение опубликовано в виде статьи Подстановка текущих даты/времени в имя файла стандартными средствами командной строки Windows).
Впоследствии обнаружилась незавершенность алгоритма - ночное и утреннее время (промежуток между 00:00 и 10:00) в зависимости от региональных настроек может содержать ведущий пробел вместо нуля (" 9:59" вместо "09:59"). Для исправления этой ошибки была добавлена одна строка, и алгоритм заработал вновь.
Примерно через год возникла необходимость вернуться к этому алгоритму, и был найден более простой вариант решения проблемы - подстановки даты и времени в имя файла. Появилась заметка Дата и время в имени файла (подстановка стандартными средствами командной строки Windows). В заметке описывается суть нового алгоритма, использующего особенности метода раскрытия переменных и свойства конструкции for /f. Рассмотрим каждый из них в отдельности. В конце будет показан еще один пример использования этой методики.

Недостатки
Вначале хотелось бы сказать о существующих недостатках. Есть одна особенность, о которой следует помнить. Этот скрипт хорошо работает даже с таким форматом даты как М/Д/ГГГГ, например для даты 14 февраля 2010. Однако это никогда не проверялось, например, для дат неделей раньше. Об этом сказано в записи от 14 февраля 2009 на странице архива Роба ван дер Вуда. Однако в большинстве случаев это работает.

Раскрытие переменных
Конструкции вида %VAR:str1=str2% указывают интерпретатору раскрыть значение переменной VAR и произвести замену всех подстрок str1 на str2 во всей строке. Это хорошая особенность, которой мы можем воспользоваться - переменная %TIME% может содержать ненужный нам ведущий пробел и нам необходимо заменить его нулем

%TIME: =0%

В данном случае str1 - это пробел, str2 - символ "ноль". Поэтому между двоеточием и знаком равенства один пробел. На всякий случай аналогичное проделываем и с переменной DATE.

set now=%DATE: =0% %TIME: =0%

Конструкция for /f
В зависимости от региональных настроек порядок элементов даты может варьироваться. Например, у нас принят формат ДД.ММ.ГГГГ, в некоторых англоговорящих странах ММ.ДД.ГГГГ. Для решения нашей проблемы надо выбрать каждую часть времени и отсортировать в нужном нам порядке - разбить строку на части по разделителям (точка ".", пробел " ", слеш "/", запятая ",", тире "-", двоеточие ":"), полученные части записать в переменные цикла и сохранить в нужном нам порядке

for /f "tokens=1-7 delims=/-:., " %%a in ( "%now%" ) do (
    set now=%%c%%b%%a_%%d%%e
)

Рассмотрим, как же эта конструкция поможет нам. for /f рассматривает входной поток (текстовая строка. файл на диске или вывод команды). В данном случае это строка, например дата и время создания этой темы 21.01.2010 21:48:50,23 (согласно настроек на моей системе). Эта строка анализируется и разбивается разделителями на отдельные фрагменты (токены).
Обратите внимание на пробел в списке разделителей - "/-:., ". Так как входная строка содержит только целочисленную информацию, разделенную разделителями, то в строке всего 7 токенов.
Для того чтобы все токены были переданы внутрь цикла указываем количество и список токенов - "tokens=1-7", то есть все семь - с первого по седьмой. Чтобы все семь токенов попали в цикл на обработку будут выделено семь переменных цикла. В заголовке цикла указано имя первой переменной %%a. Следующие переменные получат последовательно имена %%b, %%c, %%d, %%e, %%f, %%g. В первую переменную %%a попадет первый токен, во вторую, %%b - второй токен, и т.д.
И так. В этом примере порядок следующий (работает на моем компьютере, у вас может быть другой)
-- %%a - день
-- %%b - месяц
-- %%c - год
-- %%d - часы
-- %%e - минуты
-- %%f - секунды
-- %%g - сотые
Так как время 21.01.2010 21:48:50,23 из формата ДД.ММ.ГГГГ чч:мм:сс,сд надо перевести в формат ГГГГММДД_ччмм, надо взять значения переменных из списка выше в следующем порядке
-- %%c - год
-- %%b - месяц
-- %%a - день
-- %%d - часы
-- %%e - минуты

set now=%%c%%b%%a_%%d%%e

В результате получим строку вида 20100121_2148.

Этот скрипт не универсальный, он системно-зависимый: порядок отдельных частей даты и времени зависит от текущих установок на компьютере (национальные, пользовательские настройки).

Aнализ текущего времени
На форуме был задан вопрос как проанализировать текущее время:

SANIOK_AV пишет:

...нужно в процессе выполнения скрипта проанализировать текущее время, если текущее время меньше 15:00 , то пропускаем (по goto) определённую строку (блок)...

Используем раскрытие переменных с заменой подстроки - берем значение переменной TIME, производим замену пробела нулем и полученную строку сравниваем с заданной строкой времени. Так как сравнение производится лексикографически (википедия), то алгоритм выполнится корректно

if "%TIME: =0%" lss "15:00:00,00" goto end
( 2 * b ) || ! ( 2 * b )