Lote do Windows: data formatada em variável

105

Como salvo a data atual no formato AAAA-MM-DD em alguma variável em um arquivo .bat do Windows?

Análogo de shell Unix:

today=`date +%F`
echo $today
Maksym Polshcha
fonte
1
possível duplicata de data e hora do formato de script de lote
adarshr
1
adarshr, a resposta a essa pergunta usa uma maneira bastante horrível e propensa a erros de lidar com isso. Eu aconselho não usá-lo.
Joey
Este link é útil para entender as respostas abaixo. ss64.com/nt/for_f.html
smwikipedia

Respostas:

151

Você pode obter a data atual de forma independente da localidade usando

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

Em seguida, você pode extrair as partes individuais usando substrings:

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

Outra maneira, onde você obtém variáveis ​​que contêm as partes individuais, seria:

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

Muito melhor do que mexer com substrings, ao custo de poluir o namespace de sua variável.

Se você precisa do UTC em vez da hora local, o comando é mais ou menos o mesmo:

for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%
Joey
fonte
1
@ user2023861 Parece que mesmo que eu abra um prompt de comando, sempre obtenho a data / hora correta no momento da invocação do comando, não quando abri o prompt de comando.
ADTC de
5
Observe que se você executar a linha acima várias vezes, não obterá uma nova data para cada invocação, pois ela verifica se a variável está indefinida. Isso é necessário porque for /fretorna duas linhas, a última das quais vazia. Você pode resolver isso usando o set MyDate=meio. Acho que foi nisso que user2023861 tropeçou.
Joey,
1
@CharlesWood, pelo menos me esforço para obter robustez em meus próprios arquivos em lote, embora atualmente eu geralmente use o PowerShell.
Joey
1
Variáveis que serão definidas: Year, Month, Day, Hour, Minute, Second, Quarter, WeekInMonth,DayOfWeek
user
2
for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x set today=%Year%-%Month%-%Day% é uma resposta inválida: retorna um dígito mês e dia. Como obter 2 dígitos preenchidos à esquerda com zero mês e string de dia até a data?
Andrus
38

Se você deseja fazer isso usando comandos padrão do MS-DOS em um arquivo em lote, você pode usar:

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

Tenho certeza que isso pode ser melhorado ainda mais, mas isso fornece a data em 3 variáveis ​​para Dia (dd), Mês (mm) e Ano (aaaa). Você pode usá-los posteriormente em seu script de lote, conforme necessário.

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

Embora eu entenda que uma resposta foi aceita para esta pergunta, este método alternativo pode ser apreciado por muitos que procuram conseguir isso sem usar o console WMI, então espero que agregue algum valor a esta pergunta.

Richhallstoke
fonte
3
Descobri que precisava mudar isso um pouco em uma caixa do Windows 7. Os tokens precisavam ser incrementados em um: ... FOR / F "TOKENS = 2,3,4 eol = / DELIMS = /" ...
Joe Johnston
1
o mesmo no servidor Win 2012 no Azure
Kirill Yunussov
34

Use date /Tpara localizar o formato no prompt de comando.

Se o formato da data for Thu 17/03/2016usado assim:

set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%
Anup Rav
fonte
1
Esta é a resposta mais próxima da pergunta feita. Uma simples linha era tudo que eu precisava, não um programa.
DCookie
2
Acordado. Algumas das respostas aqui parecem quase como "Instale o MS SQL Server, conecte-se a um cliente SQL e execute o comando SELECT CONVERT(VARCHAR(16), GETDATE(), 112)".
isapir
2
A data e hora no formato ISO-8601 é%date:~10,4%%date:~7,2%%date:~4,2%T%time:~0,2%%time:~3,2%%time:~6,2%
isapir
3
O motivo de as outras respostas parecerem um programa é que esta resposta, embora simples, falhará se as configurações regionais do Windows não estiverem definidas da maneira que este código espera (ou seja, este código não funcionará em todos os sistemas Windows)
Daniel Scott
20

Mais duas maneiras que não dependem das configurações de tempo (ambas tiradas de Como obter dados / hora independente da localização ). E ambos também obtêm o dia da semana e nenhum deles requer permissões de administrador !:

  1. MAKECAB - funcionará em TODOS os sistemas Windows (rápido, mas cria um pequeno arquivo temporário) (o script 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 - não é um comando nativo para Windows XP e Windows Server 2003 , mas pode ser baixado do site da Microsoft . Mas está integrado em tudo, desde o Windows Vista e superior:

    @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
    

    E mais três maneiras que usam outras linguagens de script do Windows. Eles lhe darão mais flexibilidade, por exemplo, você pode obter a semana do ano, o tempo em milissegundos e assim por diante.

  3. Híbrido JScript / BATCH (precisa ser salvo como .bat). JScript está disponível em todos os sistemas do Windows NT e superior, como parte do Windows Script Host ( embora possa ser desativado por meio do registro, é um caso raro ):

    @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. Híbrido VBScript / BATCH ( é possível incorporar e executar VBScript em um arquivo em lote sem usar um arquivo temporário? ) Mesmo caso que jscript, mas a hibridização não é tão perfeita:

    :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 - pode ser instalado em todas as máquinas que possuem .NET - baixe da Microsoft ( v1 , v2 e v3 (apenas para Windows 7 e superior)). Instalado por padrão em tudo do Windows 7 / Win2008 e superior:

    C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
    
  6. Jscript.net/batch autocompilado (nunca vi uma máquina Windows sem .NET, então acho que é bastante portátil):

    @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 Não é possível obter o ano e o dia da semana. É comparativamente lento, também cria um arquivo temporário e é baseado nos registros de data e hora que o logman coloca em seus arquivos de log. Funcionará em tudo a partir do Windows XP e superior. Provavelmente nunca será usado por ninguém - incluindo eu - mas é mais uma forma ...

    @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
    

Mais informações sobre a função Get-Date .


npocmaka
fonte
8

Eu realmente gostei do método de Joey, mas pensei em expandi-lo um pouco.

Nessa abordagem, você pode executar o código várias vezes e não se preocupar com o valor de data antigo "persistente" porque já está definido.

Cada vez que você executar este arquivo em lote, ele produzirá uma representação combinada de data e hora compatível com 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%

Nesta versão, você terá que ter cuidado para não copiar / colar o mesmo código em vários lugares no arquivo, pois isso causaria rótulos duplicados. Você pode ter um rótulo separado para cada cópia ou apenas colocar esse código em seu próprio arquivo em lote e chamá-lo de seu arquivo de origem sempre que necessário.

Aardvarkk
fonte
5

Basta usar a %date%variável:

echo %date%
ProVi
fonte
5
Isso retornará a data em qualquer formato de data abreviada atualmente configurado. Isso raramente é ISO-8601.
Joey
@Joey Agreed - Estou aqui porque não é bom o suficiente para confiar.
SteveCinq de
5

De acordo com a resposta de @ProVi, basta mudar para se adequar à formatação que você precisa

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

retornará

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

EDITAR De acordo com o comentário de @Jeb, quem está correto o formato de hora acima só funcionará se o seu comando DATE / T retornar

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

É fácil editar para se adequar à sua localidade, no entanto, usando a indexação de cada caractere na string retornada pela variável de ambiente% DATE% relevante, você pode extrair as partes da string de que precisa.

por exemplo. Usar% DATE ~ 10,4% expandiria a variável de ambiente DATE e, em seguida, usaria apenas os 4 caracteres que começam no 11º (deslocamento 10) caractere do resultado expandido

Por exemplo, se usar datas no estilo dos EUA, o seguinte se aplica

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
Marca
fonte
É apenas uma solução para algumas pessoas, já que funciona apenas em alguns locais do mundo, dependendo de suas configurações de formato de data / hora
jeb
3

Eu defino uma variável de ambiente com o valor no formato numérico desejado fazendo isto:

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

Verifique este ..

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
Bhaskara Arani
fonte
2

Se você tiver o Python instalado, você pode fazer

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

Você pode adaptar facilmente a string de formato às suas necessidades.

CodeKid
fonte
2
De que forma dizer "Use python" é uma resposta à pergunta?
Ross Presser de
3
da mesma forma que usar MAKECAB, ROBOCOPY, VBSCRIPT, POWERSHELL Logman e outras sugestões aqui que você pode chamar na linha de comando?
CodeKid
Isso pode ser simplificado para python -c "import datetime;print(datetime.date.today())", porque o __str__método da dateclasse apenas chama isoformat().
onewhaleid
2

É possível usar o PowerShell e redirecionar sua saída para uma variável de ambiente usando um loop.

Na linha de comando ( 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

Em um arquivo em lote, você pode escapar %acomo %%a:

for /f "tokens=*" %%a in ('powershell get-date -format "{yyyy-MM-dd+HH:mm}"') do set td=%%a
user103004
fonte
1
A máscara deve ser assim, FOR /F "tokens=*" %%a IN ('powershell get-date -format "{yyyy\-MM\-dd\THH\:mm\:ss}"') DO SET date=%%a então use MM superior para mês e barra invertida para escapar de caracteres literais.
Quem em
1

Devido ao formato de data e hora ser uma informação específica do local, recuperá-los das variáveis% date% e% time% exigirá um esforço extra para analisar a string com a transformação do formato em consideração. Uma boa ideia é usar alguma API para recuperar a estrutura de dados e analisá-la como desejar. WMIC é uma boa escolha. O exemplo abaixo usa Win32_LocalTime . Você também pode usar Win32_CurrentTime ou 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  

Resultado:
25-04-2018_10: 03: 11

Ivellios
fonte
1

Esta é uma extensão da resposta de Joey para incluir a hora e preencher as partes com zeros.

Por exemplo, o resultado será 2019-06-01_17-25-36. Observe também que esta é a hora 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
fonte
0
echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 
Hillmee Bob
fonte
para resultados como este 20160711
Hillmee Bob
0

Estou usando o seguinte:

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

Ou em combinação com um nome de arquivo de log 'MyLogFileName':

set log_file=%date:~6,4%-%date:~3,2%-%date:~0,2%-MyLogFileName
Chris
fonte
2
Mas onde sua resposta é diferente ou melhor do que as outras 16? E já existem indícios suficientes, que esta solução só funciona para a sua localização
jeb
0

Se o PowerShell estiver disponível, você pode usar os códigos abaixo:

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

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

Aqui está o resultado:

BuildDate=200518
BuildTime=115919
吴新茂
fonte
-2

Se você não se importa em um investimento único de 10 a 30 minutos para obter uma solução confiável (que não depende das configurações regionais do Windows), continue lendo.

Vamos libertar nossas mentes. Você deseja simplificar os scripts para ficarem assim? (Suponha que você deseja definir a variável 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

Você pode. Basta construir um FormatNow.exe com C # .NET e adicioná-lo ao seu PATH.

Notas:

  1. Você pode usar qualquer edição do Visual Studio, como o Visual Studio Express, para criar o FormatNow.exe.
  2. No Visual Studio, escolha o projeto C # "Aplicativo de console", não o projeto "Aplicativo de formulários do Windows".
  3. Bom senso: o FormatNow.exe criado precisará do .NET Framework para ser executado.
  4. Bom senso: depois de adicionar FormatNow.exe à variável PATH, você precisa reiniciar o CMD para ter efeito. Também se aplica a qualquer mudança nas variáveis ​​de ambiente.

Benefícios:

  1. Não é lento (termina em 0,2 segundos).
  2. Muitos formatos são suportados https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx por exemplo, FormatNow "ddd" para obter apenas o dia da semana, FormatNow "yyyy" para obter apenas o ano
  3. Não depende das configurações regionais do Windows, portanto, sua saída é muito mais confiável. Por outro lado,% date% não fornece um formato consistente em diferentes computadores e não é confiável.
  4. Você não precisa criar tantas variáveis ​​CMD e poluir o namespace da variável.
  5. Seriam necessárias 3 linhas no script em lote para invocar o programa e obter os resultados. Deve ser razoavelmente curto.

Código-fonte do FormatNow.exe que construí com o Visual Studio 2010 (prefiro construí-lo sozinho para evitar o risco de baixar um programa desconhecido e possivelmente malicioso). Apenas copie e cole os códigos abaixo, crie o programa uma vez e você terá um formatador de data confiável para todos os usos futuros.

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());
            }
        }

    }
}

Em geral, ao lidar com lógicas complicadas, podemos torná-lo mais simples construindo um programa muito pequeno e chamando o programa para capturar a saída de volta para uma variável de script em lote. Não somos alunos e não estamos fazendo exames que nos obriguem a seguir a regra somente script em lote para resolver problemas. No ambiente de trabalho real, qualquer método (legal) é permitido. Por que ainda devemos nos ater aos recursos pobres do script em lote do Windows, que precisa de soluções alternativas para muitas tarefas simples? Por que devemos usar a ferramenta errada para o trabalho?

sken130
fonte