Пакет Windows: отформатированная дата в переменную

Как сохранить текущую дату в формате ГГГГ-ММ-ДД в некоторую переменную в файле Windows.bat?

Аналог оболочки Unix:

today='date +%F'
echo $today

Ответ 1

Вы можете получить текущую дату локально-агностическим способом, используя

for /f "skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x

Затем вы можете извлечь отдельные части с помощью подстрок:

set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%

Другим способом, в котором вы получаете переменные, которые содержат отдельные части, будет:

for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%

Намного приятнее, чем возиться с подстроками, за счет загрязнения вашего пространства имен переменных.

Если вам нужен UTC вместо локального времени, команда более или менее одинакова:

for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%

Ответ 2

Если вы хотите достичь этого, используя стандартные команды MS-DOS в пакетном файле, вы можете использовать:

FOR /F "TOKENS=1 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET dd=%%A
FOR /F "TOKENS=1,2 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET mm=%%B
FOR /F "TOKENS=1,2,3 eol=/ DELIMS=/ " %%A IN ('DATE/T') DO SET yyyy=%%C

Я уверен, что это можно улучшить, но это даёт дату в 3 переменные для дня (дд), месяца (мм) и года (гггг). Затем вы можете использовать их позже в своем пакете script по мере необходимости.

SET todaysdate=%yyyy%%mm%%dd%
echo %dd%
echo %mm%
echo %yyyy%
echo %todaysdate%

Хотя я понимаю, что для этого вопроса был принят ответ, этот альтернативный метод может быть оценен многими, желающими достичь этого, без использования консоли WMI, поэтому я надеюсь, что это добавит некоторую ценность этому вопросу.

Ответ 3

Используйте дату /T, чтобы найти формат в командной строке.

Если формат даты "Thu 03/03/2016" используется следующим образом:

set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%

Ответ 4

Еще два способа, которые не зависят от настроек времени (оба взяты из Как получить данные/время независимо от локализации). И оба также получают день недели, и ни один из них не требует прав администратора!

  1. MAKECAB - будет работать в КАЖДОЙ системе Windows (быстро, но создает небольшой временный файл) (скрипт foxidrive):

    @echo off
    pushd "%temp%"
    makecab /D RptFileName=~.rpt /D InfFileName=~.inf /f nul >nul
    for /f "tokens=3-7" %%a in ('find /i "makecab"^<~.rpt') do (
        set "current-date=%%e-%%b-%%c"
        set "current-time=%%d"
        set "weekday=%%a"
    )
    del ~.*
    popd
    echo %weekday% %current-date% %current-time%
    pause
    
  2. ROBOCOPY - это не нативная команда для Windows XP и Windows Server 2003, но ее можно скачать с сайта Microsoft. Но он встроен во все, начиная с Windows Vista и выше:

    @echo off
    setlocal
    for /f "skip=8 tokens=2,3,4,5,6,7,8 delims=: " %%D in ('robocopy /l * \ \ /ns /nc /ndl /nfl /np /njh /XF * /XD *') do (
        set "dow=%%D"
        set "month=%%E"
        set "day=%%F"
        set "HH=%%G"
        set "MM=%%H"
        set "SS=%%I"
        set "year=%%J"
    )
    
    echo Day of the week: %dow%
    echo Day of the month : %day%
    echo Month : %month%
    echo hour : %HH%
    echo minutes : %MM%
    echo seconds : %SS%
    echo year : %year%
    endlocal
    

    И еще три способа использования других языков сценариев Windows. Они дадут вам больше гибкости, например, вы можете получить неделю года, время в миллисекундах и так далее.

  3. Гибрид JScript/BATCH (необходимо сохранить как .bat). JScript доступен в каждой системе, начиная с Windows NT и выше, как часть Windows Script Host (хотя в редких случаях его можно отключить через реестр):

    @if (@X)==(@Y) @end /* ---Harmless hybrid line that begins a JScript comment
    
    @echo off
    cscript //E:JScript //nologo "%~f0"
    exit /b 0
    *------------------------------------------------------------------------------*/
    
    function GetCurrentDate() {
        // Today date time which will used to set as default date.
        var todayDate = new Date();
        todayDate = todayDate.getFullYear() + "-" +
                       ("0" + (todayDate.getMonth() + 1)).slice(-2) + "-" +
                       ("0" + todayDate.getDate()).slice(-2) + " " + ("0" + todayDate.getHours()).slice(-2) + ":" +
                       ("0" + todayDate.getMinutes()).slice(-2);
    
        return todayDate;
    }
    
    WScript.Echo(GetCurrentDate());
    
  4. Гибрид VBScript/BATCH (возможно ли встроить и выполнить VBScript в пакетном файле без использования временного файла?) В том же случае, что и в jscript, но гибридизация не так совершенна:

    :sub echo(str) :end sub
    echo off
    '>nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul
    '& echo current date:
    '& cscript /nologo /E:vbscript "%~f0"
    '& exit /b
    
    '0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if specified: hh:mm:ss PM/AM.
    '1 = vbLongDate - Returns date: weekday, monthname, year
    '2 = vbShortDate - Returns date: mm/dd/yy
    '3 = vbLongTime - Returns time: hh:mm:ss PM/AM
    '4 = vbShortTime - Return time: hh:mm
    
    WScript.echo  Replace(FormatDateTime(Date, 1), ", ", "-")
    
  5. PowerShell - может быть установлен на любой машине с .NET - скачать с Microsoft (v1, v2 и v3 (только для Windows 7 и выше)). Установлен по умолчанию на все формы Windows 7/Win2008 и выше:

    C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
    
  6. Самоскомпилированный jscript.net/batch (я никогда не видел машины с Windows без .NET, так что я думаю, что это довольно переносимо):

    @if (@X)==(@Y) @end /****** silent line that start jscript comment ******
    
    @echo off
    ::::::::::::::::::::::::::::::::::::
    :::       Compile the script    ::::
    ::::::::::::::::::::::::::::::::::::
    setlocal
    if exist "%~n0.exe" goto :skip_compilation
    
    set "frm=%SystemRoot%\Microsoft.NET\Framework\"
    :: searching the latest installed .net framework
    for /f "tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n "%SystemRoot%\Microsoft.NET\Framework\v*"') do (
        if exist "%%v\jsc.exe" (
            rem :: the javascript.net compiler
            set "jsc=%%~dpsnfxv\jsc.exe"
            goto :break_loop
        )
    )
    echo jsc.exe not found && exit /b 0
    :break_loop
    
    
    call %jsc% /nologo /out:"%~n0.exe" "%~dpsfnx0"
    ::::::::::::::::::::::::::::::::::::
    :::       End of compilation    ::::
    ::::::::::::::::::::::::::::::::::::
    :skip_compilation
    
    "%~n0.exe"
    
    exit /b 0
    
    
    ****** End of JScript comment ******/
    import System;
    import System.IO;
    
    var dt=DateTime.Now;
    Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss"));
    
  7. Логман Это не может получить год и день недели. Он сравнительно медленный, также создает временный файл и основан на отметках времени, которые logman помещает в свои файлы журналов. Будет работать все, начиная с Windows XP и выше. Это, вероятно, никогда не будет использоваться никем - включая меня - но это еще один способ...

    @echo off
    setlocal
    del /q /f %temp%\timestampfile_*
    
    Logman.exe stop ts-CPU 1>nul 2>&1
    Logman.exe delete ts-CPU 1>nul 2>&1
    
    Logman.exe create counter ts-CPU  -sc 2 -v mmddhhmm -max 250 -c "\Processor(_Total)\%% Processor Time" -o %temp%\timestampfile_ >nul
    Logman.exe start ts-CPU 1>nul 2>&1
    
    Logman.exe stop ts-CPU >nul 2>&1
    Logman.exe delete ts-CPU >nul 2>&1
    for /f "tokens=2 delims=_." %%t in  ('dir /b %temp%\timestampfile_*^&del /q/f %temp%\timestampfile_*') do set timestamp=%%t
    
    echo %timestamp%
    echo MM: %timestamp:~0,2%
    echo dd: %timestamp:~2,2%
    echo hh: %timestamp:~4,2%
    echo mm: %timestamp:~6,2%
    
    endlocal
    exit /b 0
    

Более подробная информация о функции Get-Date.


Ответ 5

Мне очень понравился метод Joey, но я подумал, что немного расширю его.

В этом подходе вы можете запускать код несколько раз и не беспокоиться о том, что старое значение даты "придерживается", потому что оно уже определено.

Каждый раз, когда вы запускаете этот командный файл, он выводит совместимое с ISO 8601 представление даты и времени.

FOR /F "skip=1" %%D IN ('WMIC OS GET LocalDateTime') DO (SET LIDATE=%%D & GOTO :GOT_LIDATE)
:GOT_LIDATE
SET DATETIME=%LIDATE:~0,4%-%LIDATE:~4,2%-%LIDATE:~6,2%T%LIDATE:~8,2%:%LIDATE:~10,2%:%LIDATE:~12,2%
ECHO %DATETIME%

В этой версии вам нужно быть осторожным, чтобы не копировать и не вставлять один и тот же код в несколько мест в файле, потому что это приведет к дублированию меток. Вы можете либо иметь отдельную метку для каждой копии, либо просто поместить этот код в свой пакетный файл и вызвать его из исходного файла, где это необходимо.

Ответ 6

Просто используйте переменную %date%:

echo %date%

Ответ 7

В соответствии с ответом @ProVi просто измените его в соответствии с требуемым форматированием

echo %DATE:~10,4%-%DATE:~7,2%-%DATE:~4,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%

вернет

yyyy-MM-dd hh:mm:ss
2015-09-15 18:36:11

ИЗМЕНИТЬ Согласно комментарию @Jeb, кто прав, указанный выше формат времени будет работать, только если ваша команда DATE/T вернет

ddd dd/mm/yyyy
Thu 17/09/2015

Легко редактировать в соответствии с вашей локалью, однако, используя индексирование каждого символа в строке, возвращаемой соответствующей переменной среды% DATE%, вы можете извлечь нужные части строки.

например. Использование% DATE ~ 10,4% расширит переменную среды DATE, а затем будет использовать только 4 символа, которые начинаются с 11-го (смещенного 10) символа расширенного результата

Например, если использовать даты в стиле США, тогда применяется

ddd mm/dd/yyyy
Thu 09/17/2015

echo %DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%
2015-09-17 18:36:11

Ответ 8

Я установил переменную окружения на значение в числовом формате, желая сделать это:

FOR /F "tokens=1,2,3,4 delims=/ " %a IN ('echo %date%') DO set DateRun=%d-%b-%c

Ответ 9

Можно использовать PowerShell и перенаправить его вывод в переменную среды с помощью цикла.

Из командной строки (cmd):

for /f "tokens=*" %a in ('powershell get-date -format "{yyyy-mm-dd+HH:mm}"') do set td=%a

echo %td%
2016-25-02+17:25

В пакетном файле вы можете экранировать %a как %%a:

for /f "tokens=*" %%a in ('powershell get-date -format "{yyyy-mm-dd+HH:mm}"') do set td=%%a

Ответ 10

Проверьте это.

for /f "tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set "dt=%%a"
set "YY=%dt:~2,2%" & set "YYYY=%dt:~0,4%" & set "MM=%dt:~4,2%" & set "DD=%dt:~6,2%"
set "HH=%dt:~8,2%" & set "Min=%dt:~10,2%" & set "Sec=%dt:~12,2%" & set "MS=%dt:~15,3%"
set "datestamp=%YYYY%%MM%%DD%" & set "timestamp=%HH%%Min%%Sec%" & set "fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%-%MS%"
echo datestamp: "%datestamp%"
echo timestamp: "%timestamp%"
echo fullstamp: "%fullstamp%"
pause

Ответ 11

Если у вас установлен Python, вы можете сделать

python -c "import datetime;print(datetime.date.today().strftime('%Y-%m-%d'))"

Вы можете легко адаптировать строку формата к вашим потребностям.

Ответ 12

Поскольку формат даты и времени является специфичной для местоположения информацией, для извлечения их из переменных% date% и% time% потребуется дополнительное усилие для анализа строки с учетом преобразования формата. Хорошей идеей является использование некоторого API для извлечения структуры данных и анализа по вашему желанию. WMIC - это хороший выбор. Ниже приведен пример использования Win32_LocalTime. Вы также можете использовать Win32_CurrentTime или Win32_UTCTime.

@echo off  
SETLOCAL ENABLEDELAYEDEXPANSION  
for /f %%x in ('wmic path Win32_LocalTime get /format:list ^| findstr "="') do set %%x  
set yyyy=0000%Year%  
set mmmm=0000%Month%  
set dd=00%Day%  
set hh=00%Hour%  
set mm=00%Minute%  
set ss=00%Second%  
set ts=!yyyy:~-4!-!mmmm:~-2!-!dd:~-2!_!hh:~-2!:!mm:~-2!:!ss:~-2!  
echo %ts%  
ENDLOCAL  

Результат:
2018-04-25_10: 03: 11

Ответ 13

echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 

Ответ 14

Это расширение ответа Джоуи, которое включает время и дополняет части нулями.

Например, результат будет 2019-06-01_17-25-36. Также обратите внимание, что это время UTC.

  for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x

  set Month=0%Month%
  set Month=%Month:~-2%
  set Day=0%Day%
  set Day=%Day:~-2%
  set Hour=0%Hour%
  set Hour=%Hour:~-2%
  set Minute=0%Minute%
  set Minute=%Minute:~-2%
  set Second=0%Second%
  set Second=%Second:~-2%

  set TimeStamp=%Year%-%Month%-%Day%_%Hour%-%Minute%-%Second%

Ответ 15

Если вы не возражаете против одноразовых инвестиций от 10 до 30 минут, чтобы получить надежное решение (это не зависит от настроек региона Windows), пожалуйста, прочитайте.

Освободите наши умы. Вы хотите упростить сценарии, чтобы просто выглядеть так? (Предположим, вы хотите установить переменную LOG_DATETIME)

FOR /F "tokens=* USEBACKQ" %%F IN (`FormatNow "yyyy-MM-dd"`) DO (
  Set LOG_DATETIME=%%F
)

echo I am going to write log to Testing_%LOG_DATETIME%.log

Вы можете. Просто создайте файл FormatNow.exe с С#.NET и добавьте его в свой PATH.

Примечания:

  • Вы можете использовать любую версию Visual Studio, например Visual Studio Express, для создания FormatNow.exe.
  • В Visual Studio выберите проект "Консольное приложение" С#, а не проект "Приложение Windows Forms".
  • Здравый смысл: для встроенного файла FormatNow.exe потребуется .NET Framework для запуска.
  • Здравый смысл: после добавления FormatNow.exe в переменную PATH вам необходимо перезапустить CMD, чтобы вступить в силу. Это также относится к любым изменениям переменных среды.

Преимущества:

  • Это не медленно (заканчивается в течение 0.2 секунд).
  • Поддерживаются многие форматы https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx например FormatNow "ddd", чтобы получить только день недели, FormatNow "yyyy", чтобы получить только год
  • Это не зависит от настроек региона Windows, поэтому его вывод намного надежнее. С другой стороны,% date% не дает согласованного формата для разных компьютеров и не является надежным.
  • Вам не нужно создавать так много CMD-переменных и загрязнять пространство имен переменных.
  • Для запуска программы и получения результатов потребуется 3 строки в пакете script. Он должен быть достаточно коротким.

Исходный код FormatNow.exe, который я создал с помощью Visual Studio 2010 (я предпочитаю самостоятельно его создавать, чтобы избежать риска загрузки неизвестной, возможно, вредоносной программы). Просто скопируйте и вставьте коды ниже, создайте программу один раз, а затем у вас есть надежный формат даты для всех будущих использования.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;

namespace FormatNow
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                if (args.Length < 1)
                {
                    throw new ArgumentException("Missing format");
                }
                string format = args[0];
                Console.Write(DateTime.Now.ToString(format, CultureInfo.InvariantCulture.DateTimeFormat));
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

    }
}

В общем случае, имея дело со сложными логиками, мы можем сделать это проще, построив очень маленькую программу и вызывая программу для последующего захвата вывода обратно в пакетную переменную script. Мы не студенты, и мы не сдаем экзамены, требуя от нас следовать пакетному решению script только для решения проблем. В реальной рабочей среде допускается любой (юридический) метод. Почему мы должны по-прежнему придерживаться плохих возможностей пакетной установки Windows script, которым нужны обходные пути для многих простых задач? Почему мы должны использовать неправильный инструмент для работы?