Lote de Windows: fecha formateada en variable

105

¿Cómo guardo la fecha actual en formato AAAA-MM-DD en alguna variable en un archivo .bat de Windows?

Análogo de shell de Unix:

today=`date +%F`
echo $today
Maksym Polshcha
fuente
1
adarshr, la respuesta a esa pregunta utiliza una forma bastante horrible y propensa a errores de abordarla. Aconsejaría no usarlo.
Joey
Este enlace es útil para comprender las respuestas a continuación. ss64.com/nt/for_f.html
smwikipedia

Respuestas:

151

Puede obtener la fecha actual de forma independiente de la configuración regional utilizando

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

Luego, puede extraer las partes individuales usando subcadenas:

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

Otra forma, donde obtienes variables que contienen las partes individuales, sería:

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

Mucho mejor que jugar con subcadenas, a expensas de contaminar el espacio de nombres de las variables.

Si necesita UTC en lugar de la hora local, el comando es más o menos el mismo:

for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr "="') do set %%x
set today=%Year%-%Month%-%Day%
Joey
fuente
1
@ user2023861 Parece que incluso si abro un símbolo del sistema, siempre obtengo la fecha / hora correcta en el momento de la invocación del comando, no cuando abrí el símbolo del sistema.
ADTC
5
Tenga en cuenta que si ejecuta la línea anterior varias veces, no obtendrá una nueva fecha para cada invocación, ya que verifica que la variable no esté definida. Esto es necesario porque for /fdevuelve dos líneas, la última de las cuales está vacía. Puedes resolver eso usando set MyDate=en el medio. Supongo que con eso se tropezó el usuario2023861.
Joey
1
@CharlesWood, al menos me esfuerzo por la solidez en mis propios archivos por lotes, aunque en estos días a menudo uso PowerShell.
Joey
1
Las variables que se establecerán: Year, Month, Day, Hour, Minute, Second, Quarter, WeekInMonth,DayOfWeek
usuario
2
for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr "="') do set %%x set today=%Year%-%Month%-%Day% es una respuesta inválida: devuelve un dígito de mes y día. ¿Cómo se rellena la izquierda de 2 dígitos con mes cero y cadena del día hasta la fecha?
Andrus
38

Si desea lograr esto usando comandos estándar de MS-DOS en un archivo por lotes, puede 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

Estoy seguro de que esto se puede mejorar aún más, pero esto da la fecha en 3 variables para Día (dd), Mes (mm) y Año (aaaa). Luego, puede usarlos más adelante en su secuencia de comandos por lotes según sea necesario.

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

Si bien entiendo que se ha aceptado una respuesta para esta pregunta, este método alternativo puede ser apreciado por muchos que buscan lograrlo sin usar la consola WMI, así que espero que agregue algo de valor a esta pregunta.

Richhallstoke
fuente
3
Descubrí que necesitaba cambiar esto ligeramente en una caja de Windows 7. Los tokens debían incrementarse en uno: ... FOR / F "TOKENS = 2,3,4 eol = / DELIMS = /" ...
Joe Johnston
1
Lo mismo en el servidor Win 2012 en Azure
Kirill Yunussov
34

Úselo date /Tpara buscar el formato en el símbolo del sistema.

Si el formato de fecha es Thu 17/03/2016 usa así:

set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2%
echo %datestr%
Anup Rav
fuente
1
Esta es la respuesta más cercana a la pregunta formulada. Todo lo que necesitaba era una simple frase, no un programa.
DCookie
2
Convenido. Algunas de las respuestas aquí se parecen casi a "Instale MS SQL Server, conéctese con un cliente SQL y ejecute el comando SELECT CONVERT(VARCHAR(16), GETDATE(), 112)".
isapir
2
La fecha y hora en formato ISO-8601 es%date:~10,4%%date:~7,2%%date:~4,2%T%time:~0,2%%time:~3,2%%time:~6,2%
isapir
3
La razón por la que las otras respuestas parecen un programa es que esta respuesta, aunque simple, fallará si la configuración regional de Windows no está configurada de la manera que espera este código (es decir, este código no funcionará en todos los sistemas Windows)
Daniel Scott
20

Dos formas más que no dependen de la configuración de la hora (ambas tomadas de Cómo obtener datos / hora independientemente de la localización ). ¡Y ambos también obtienen el día de la semana y ninguno de ellos requiere permisos de administrador !:

  1. MAKECAB : funcionará en TODOS los sistemas Windows (rápido, pero crea un pequeño archivo temporal) (el 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 : no es un comando nativo para Windows XP y Windows Server 2003 , pero se puede descargar del sitio de Microsoft . Pero está integrado en todo, desde Windows Vista y versiones posteriores:

    @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
    

    Y tres formas más que utilizan otros lenguajes de script de Windows. Le darán más flexibilidad, por ejemplo, puede obtener la semana del año, la hora en milisegundos, etc.

  3. Híbrido JScript / BATCH (debe guardarse como .bat). JScript está disponible en todos los sistemas de Windows NT y superior, como parte de Windows Script Host ( aunque se puede desactivar a través del registro, es un 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. VBScript / BATCH híbrido ( ¿Es posible incrustar y ejecutar VBScript dentro de un archivo por lotes sin usar un archivo temporal? ) En el mismo caso que jscript, pero la hibridación no es tan perfecta:

    :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 : se puede instalar en todas las máquinas que tengan .NET; descargar de Microsoft ( v1 , v2 y v3 (solo para Windows 7 y superior)). Instalado por defecto en todo desde Windows 7 / Win2008 y superior:

    C:\> powershell get-date -format "{dd-MMM-yyyy HH:mm}"
    
  6. Jscript.net/batch autocompilado (nunca he visto una máquina con Windows sin .NET, así que creo que es 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 Esto no puede obtener el año y el día de la semana. Es comparativamente lento, también crea un archivo temporal y se basa en las marcas de tiempo que logman coloca en sus archivos de registro. Funcionará todo desde Windows XP y superior. Probablemente nadie lo use nunca, incluido yo, pero es una forma más ...

    @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
    

Más información sobre la función Get-Date .


npocmaka
fuente
8

Me gustó mucho el método de Joey, pero pensé en ampliarlo un poco.

En este enfoque, puede ejecutar el código varias veces y no preocuparse por que el valor de fecha anterior "se quede" porque ya está definido.

Cada vez que ejecute este archivo por lotes, generará una representación combinada de fecha y hora compatible con 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%

En esta versión, deberá tener cuidado de no copiar / pegar el mismo código en varios lugares del archivo porque eso causaría etiquetas duplicadas. Puede tener una etiqueta separada para cada copia o simplemente poner este código en su propio archivo por lotes y llamarlo desde su archivo fuente cuando sea necesario.

oso hormiguero
fuente
5

Solo usa la %date%variable:

echo %date%
ProVi
fuente
5
Esto devolverá la fecha en cualquiera que sea el formato de fecha corta configurado actualmente. Rara vez es ISO-8601.
Joey
@Joey estuvo de acuerdo: estoy aquí porque esto no es lo suficientemente bueno como para confiar.
SteveCinq
5

Según la respuesta de @ProVi, simplemente cambie para adaptarse al formato que necesita

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

volverá

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

EDITAR Según el comentario de @Jeb, quién tiene razón, el formato de hora anterior solo funcionará si su comando DATE / T regresa

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

Sin embargo, es fácil de editar para que se adapte a su configuración regional, al usar la indexación de cada carácter en la cadena devuelta por la variable de entorno% DATE% relevante, puede extraer las partes de la cadena que necesita.

p.ej. El uso de% DATE ~ 10,4% expandiría la variable de entorno DATE y luego usaría solo los 4 caracteres que comienzan en el undécimo carácter (desplazamiento 10) del resultado expandido

Por ejemplo, si usa fechas con estilo de EE. UU., Se aplica lo siguiente

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
fuente
Es solo una solución para algunas personas, ya que esto solo funciona en algunas ubicaciones del mundo, según la configuración de formato de fecha / hora
jeb
3

Establecí una variable de entorno en el valor en el formato numérico deseado haciendo esto:

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

Revisa 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
fuente
2

Si tiene Python instalado, puede hacer

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

Puede adaptar fácilmente la cadena de formato a sus necesidades.

CodeKid
fuente
2
¿De qué manera decir "Use Python" es una respuesta a la pregunta?
Ross Presser
3
de la misma manera que usa MAKECAB, ROBOCOPY, VBSCRIPT, POWERSHELL Logman y otras sugerencias aquí que puede llamar en la línea de comando?
CodeKid
Esto se puede simplificar python -c "import datetime;print(datetime.date.today())", porque el __str__método de la dateclase solo llama isoformat().
onewhaleid
2

Es posible usar PowerShell y redirigir su salida a una variable de entorno mediante un bucle.

Desde la línea 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

En un archivo por lotes, puede escapar %acomo %%a:

for /f "tokens=*" %%a in ('powershell get-date -format "{yyyy-MM-dd+HH:mm}"') do set td=%%a
usuario103004
fuente
1
La máscara debería ser así, FOR /F "tokens=*" %%a IN ('powershell get-date -format "{yyyy\-MM\-dd\THH\:mm\:ss}"') DO SET date=%%a así que use MM superior para el mes y barra invertida para escapar de los caracteres literales.
Whome
1

Debido a que el formato de fecha y hora es información específica de la ubicación, recuperarlos de las variables% date% y% time% requerirá un esfuerzo adicional para analizar la cadena con la transformación de formato en consideración. Una buena idea es utilizar alguna API para recuperar la estructura de datos y analizarla como desee. WMIC es una buena opción. El siguiente ejemplo usa Win32_LocalTime . También puede utilizar Win32_CurrentTime o 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:
2018-04-25_10: 03: 11

Ivellios
fuente
1

Esta es una extensión de la respuesta de Joey para incluir el tiempo y rellenar las partes con ceros.

Por ejemplo, el resultado será 2019-06-01_17-25-36. También tenga en cuenta que esta es la 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
fuente
0
echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 
Hillmee Bob
fuente
para una salida como esta 20160711
Hillmee Bob
0

Estoy usando lo siguiente:

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

O en combinación con un nombre de archivo de registro 'MyLogFileName':

set log_file=%date:~6,4%-%date:~3,2%-%date:~0,2%-MyLogFileName
Chris
fuente
2
Pero, ¿dónde es diferente o mejor tu respuesta que las otras 16? Y ya hay suficientes indicios de que esta solución solo funciona para su localización
jeb
0

Si powershell está disponible, puede usar los siguientes códigos:

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

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

Aquí está el resultado:

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

Si no le importa una inversión única de 10 a 30 minutos para obtener una solución confiable (que no depende de la configuración regional de Windows), siga leyendo.

Liberemos nuestras mentes. ¿Quiere simplificar los scripts para que se vean así? (Suponga que desea establecer la variable 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

Usted puede. Simplemente cree un FormatNow.exe con C # .NET y agréguelo a su PATH.

Notas:

  1. Puede utilizar cualquier edición de Visual Studio, como Visual Studio Express, para compilar FormatNow.exe.
  2. En Visual Studio, elija el proyecto C # "Aplicación de consola", no el proyecto "Aplicación de Windows Forms".
  3. Sentido común: el FormatNow.exe construido necesitará .NET Framework para ejecutarse.
  4. Sentido común: después de agregar FormatNow.exe a la variable PATH, debe reiniciar CMD para que surta efecto. También se aplica a cualquier cambio en las variables de entorno.

Beneficios:

  1. No es lento (termina en 0,2 segundos).
  2. Se admiten muchos formatos https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx por ejemplo, FormatNow "ddd" para obtener solo el día de la semana, FormatNow "yyyy" para obtener solo el año
  3. No depende de la configuración regional de Windows, por lo que su salida es mucho más confiable. Por otro lado,% date% no proporciona un formato consistente en diferentes computadoras y no es confiable.
  4. No es necesario crear tantas variables CMD y contaminar el espacio de nombres de las variables.
  5. Se necesitarían 3 líneas en el script por lotes para invocar el programa y obtener los resultados. Debe ser lo suficientemente corto.

Código fuente de FormatNow.exe que creé con Visual Studio 2010 (prefiero compilarlo yo mismo para evitar el riesgo de descargar un programa desconocido, posiblemente malicioso). Simplemente copie y pegue los códigos a continuación, compile el programa una vez y luego tendrá un formateador de fecha confiable para todos los 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());
            }
        }

    }
}

En general, cuando se trata de lógicas complicadas, podemos simplificarlo construyendo un programa muy pequeño y llamando al programa para que capture la salida de nuevo en una variable de script por lotes. No somos estudiantes y no estamos tomando exámenes que requieran que sigamos la regla de solo guiones por lotes para resolver problemas. En un entorno de trabajo real, se permite cualquier método (legal). ¿Por qué deberíamos ceñirnos a las pobres capacidades del script por lotes de Windows que necesita soluciones para muchas tareas simples? ¿Por qué deberíamos utilizar la herramienta incorrecta para el trabajo?

sken130
fuente