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

105

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

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

today=`date +%F`
echo $today
Максим Польща
источник
1
adarshr, ответ на этот вопрос использует довольно ужасный и подверженный ошибкам способ решения проблемы. Советую не использовать.
Joey
Эта ссылка полезна для понимания приведенных ниже ответов. ss64.com/nt/for_f.html
smwikipedia

Ответы:

151

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

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%
Джоуи
источник
1
@ user2023861 Похоже, что даже если я открываю командную строку, я всегда получаю правильную дату / время в момент вызова команды, а не тогда, когда я открывал командную строку.
ADTC
5
Обратите внимание, что если вы запускаете указанную выше строку несколько раз, вы не получите новую дату для каждого вызова, поскольку он проверяет, не определена ли переменная. Это необходимо, потому что for /fвозвращает две строки, последняя из которых является пустой. Вы можете решить эту проблему, используя set MyDate=промежуточные. Думаю, вот на что споткнулся user2023861.
Joey
1
@CharlesWood, по крайней мере, я стремлюсь к надежности моих собственных командных файлов, хотя в наши дни я часто вместо этого использую PowerShell.
Joey
1
Переменные , которые будут установлены: Year, Month, Day, Hour, Minute, Second, Quarter, WeekInMonth,DayOfWeek
пользователь
2
for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x set today=%Year%-%Month%-%Day% неверный ответ: возвращает однозначный месяц и день. Как получить 2-значное левое дополнение с нулевой строкой месяца и дня до даты?
Андрус
39

Если вы хотите добиться этого с помощью стандартных команд 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 переменных: день (дд), месяц (мм) и год (гггг). Затем вы можете использовать их позже в своем пакетном сценарии по мере необходимости.

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

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

Richhallstoke
источник
3
Я обнаружил, что мне нужно немного изменить это в окне Windows 7. Количество токенов необходимо увеличить на единицу: ... FOR / F "TOKENS = 2,3,4 eol = / DELIMS = /" ...
Джо Джонстон
1
то же самое на Win server 2012 на Azure
Кирилл Юнусов 05
34

Используйте date /Tдля поиска формата в командной строке.

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

set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%
Ануп Рав
источник
1
Это наиболее близкий ответ на заданный вопрос. Все, что мне было нужно, - это простой однострочный текст, а не программа.
DCookie
2
Согласовано. Некоторые ответы здесь выглядят почти как «Установите MS SQL Server, подключитесь к клиенту SQL и выполните команду SELECT CONVERT(VARCHAR(16), GETDATE(), 112)».
isapir
2
Даты и времени в формате ISO-8601%date:~10,4%%date:~7,2%%date:~4,2%T%time:~0,2%%time:~3,2%%time:~6,2%
isapir
3
Причина того, что другие ответы выглядят как программа, заключается в том, что этот ответ, хотя и простой, не даст результата, если ваши региональные настройки Windows не настроены так, как ожидает этот код (т.е. этот код не будет работать в каждой системе Windows)
Дэниел Скотт
20

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

  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 Не может получить год и день недели. Он сравнительно медленный, также создает временный файл и основан на отметках времени, которые 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 .


нпочмака
источник
8

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

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

Каждый раз, когда вы запускаете этот командный файл, он выводит комбинированное представление даты и времени, совместимое с 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%

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

муравьед
источник
5

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

echo %date%
ProVi
источник
5
Это вернет дату в любом текущем настроенном коротком формате даты. Это редко ISO-8601.
Joey
@Joey Agreed - я здесь, потому что этого недостаточно, чтобы полагаться на него.
SteveCinq
5

В соответствии с ответом @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

EDIT Согласно @Jeb комментарий, которого правильно выше формат времени будет работать только , если ваша дата / возвращает 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
отметка
источник
Это решение только для некоторых людей, так как это работает только в некоторых местах в мире, в зависимости от ваших настроек формата даты / времени
jeb
3

Я установил для переменной среды значение в желаемом числовом формате, выполнив следующие действия:

FOR /F "tokens=1,2,3,4 delims=/ " %a IN ('echo %date%') DO set DateRun=%d-%b-%c
Будет
источник
2

Отметьте это ..

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
Бхаскара Арани
источник
2

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

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

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

CodeKid
источник
2
Каким образом можно сказать «Используйте Python» в качестве ответа на вопрос?
Росс Прессер
3
таким же образом, как при использовании MAKECAB, ROBOCOPY, VBSCRIPT, POWERSHELL Logman и других предложений, которые вы можете вызвать из командной строки?
CodeKid
Это можно упростить python -c "import datetime;print(datetime.date.today())", потому что __str__метод dateкласса просто вызывает isoformat().
onewhaleid
2

Можно использовать 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
user103004
источник
1
Если маска должна быть FOR /F "tokens=*" %%a IN ('powershell get-date -format "{yyyy\-MM\-dd\THH\:mm\:ss}"') DO SET date=%%a такой, используйте верхний MM для месяца и обратную косую черту, чтобы избежать буквальных символов.
Whome
1

Из-за того, что формат даты и времени - это информация о местоположении, получение их из переменных% 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

Ivellios
источник
1

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

Например, результат будет 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%
Datchung
источник
0
echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 
Хиллми Боб
источник
для вывода наподобие этого 20160711
Hillmee Bob
0

Я использую следующее:

set iso_date=%date:~6,4%-%date:~3,2%-%date:~0,2%

Или в сочетании с именем файла журнала MyLogFileName:

set log_file=%date:~6,4%-%date:~3,2%-%date:~0,2%-MyLogFileName
Крис
источник
2
Но чем ваш ответ отличается от других 16 или лучше? И уже есть достаточно намеков, что это решение работает только для вашей локализации
jeb
0

Если PowerShell доступен, вы можете использовать следующие коды:

# get date
$BuildDate=(get-date -format "yyMMdd")
echo BuildDate=$BuildDate

# get time
$BuildTime=(get-date -format "hhmmss")
echo BuildTime=$BuildTime

Вот результат:

BuildDate=200518
BuildTime=115919
吴新茂
источник
-2

Если вы не возражаете против одноразового вложения от 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 с C # .NET и добавьте его в свой PATH.

Ноты:

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

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

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

Исходный код 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());
            }
        }

    }
}

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

sken130
источник