Locale-Independent Date and Time Formatting in Windows Batch Files: A Robust Solution for YYYY-MM-DD


1 views

When working with batch files on Windows systems, many developers encounter frustration with the built-in %DATE% and %TIME% environment variables. These variables return values formatted according to the system's regional settings, making scripts non-portable across different locales.

:: German locale output example
echo %DATE%
:: Output: 26.1.2023

:: US locale output example
echo %DATE%
:: Output: 01/26/2023

Common workarounds often involve parsing the date string with locale-specific delimiters, but these solutions break when the script runs on systems with different regional settings:

:: Fragile German-specific solution
for /f "tokens=1-3 delims=. " %%a in ('date /t') do (
    set year=%%c
    set month=%%b
    set day=%%a
)

For a truly locale-independent solution, we can use Windows Management Instrumentation Command-line (WMIC):

:: Universal date format solution
for /f "tokens=2 delims==" %%A in ('wmic os get localdatetime /value') do (
    set datetime=%%A
)
set datepart=%datetime:~0,8%
set formatteddate=%datepart:~0,4%-%datepart:~4,2%-%datepart:~6,2%
echo %formatteddate%
:: Output always in YYYY-MM-DD format

If your system has PowerShell available, you can leverage its consistent date formatting:

:: PowerShell integration method
for /f "delims=" %%A in ('powershell -command "Get-Date -format 'yyyy-MM-dd'"') do (
    set uniformdate=%%A
)
echo %uniformdate%

For frequent use, consider creating reusable date functions in your batch scripts:

:: Batch function for consistent dates
:GetUniformDate
for /f "tokens=2 delims==" %%A in ('wmic os get localdatetime /value') do (
    set datetime=%%A
)
set %1=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%
goto :EOF

:: Usage example
call :GetUniformDate today
echo %today%

While WMIC is the most reliable solution, it's worth noting that it has some overhead. For performance-critical applications where you know the locale, cached parsing might be acceptable:

:: Cached solution for known environments
if not defined _DateMethod set _DateMethod=WMIC
if /i "%_DateMethod%"=="WMIC" (
    call :GetUniformDate currentdate
) else (
    for /f "tokens=2-4 delims=/ " %%a in ('date /t') do (
        set currentdate=%%c-%%a-%%b
    )
)

The same principles apply to time formatting. Here's a complete solution for both date and time:

:: Complete timestamp solution
for /f "tokens=2 delims==" %%A in ('wmic os get localdatetime /value') do (
    set datetime=%%A
)
set uniformdate=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%
set uniformtime=%datetime:~8,2%:%datetime:~10,2%:%datetime:~12,2%
echo Date: %uniformdate% Time: %uniformtime%

Windows batch scripts often rely on %DATE% and %TIME% environment variables, but these inherit the system's regional settings. This causes inconsistent formatting across different locales, making automated file naming and sorting problematic.

Here are three reliable approaches to get locale-independent dates in YYYY-MM-DD format:

:: Method 1: Using WMIC (Windows Management Instrumentation)
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /value') do set datetime=%%I
set datepart=%datetime:~0,8%
set formatteddate=%datepart:~0,4%-%datepart:~4,2%-%datepart:~6,2%
echo %formatteddate%
:: Method 2: PowerShell Integration (Windows 7+)
for /f %%i in ('powershell -command "Get-Date -Format 'yyyy-MM-dd'"') do set uniformdate=%%i
echo %uniformdate%

For consistent 24-hour time formatting (HH:MM:SS):

:: Using WMIC for time
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /value') do set datetime=%%I
set timepart=%datetime:~8,6%
set formattedtime=%timepart:~0,2%:%timepart:~2,2%:%timepart:~4,2%
echo %formattedtime%

For legacy systems without WMIC, use this fallback approach:

:: Cross-version compatible solution
for /f "tokens=1-3 delims=/ " %%a in ('date /t') do (
    set mm=%%a
    set dd=%%b
    set yyyy=%%c
)
if %mm% LSS 10 set mm=0%mm%
if %dd% LSS 10 set dd=0%dd%
set isodate=%yyyy%-%mm%-%dd%
echo %isodate%

Here's a complete script for generating timestamped log files:

@echo off
:: Get standardized date/time
for /f "tokens=2 delims==" %%I in ('wmic os get localdatetime /value') do set datetime=%%I
set logdate=%datetime:~0,4%-%datetime:~4,2%-%datetime:~6,2%
set logtime=%datetime:~8,2%-%datetime:~10,2%-%datetime:~12,2%

:: Create log file
set logfile=output_%logdate%_%logtime%.log
echo Processing started at %logtime% on %logdate% > %logfile%

:: Your script commands here...
echo Additional output >> %logfile%

For scripts requiring specific formatting temporarily:

:: Save current locale
for /f "tokens=2,3 delims=," %%a in ('reg query "HKCU\Control Panel\International" /v sShortDate') do set originalshortdate=%%b

:: Set to ISO format temporarily
reg add "HKCU\Control Panel\International" /v sShortDate /t REG_SZ /d "yyyy-MM-dd" /f > nul

:: Now %DATE% will use ISO format
echo Current date: %DATE%

:: Restore original setting
reg add "HKCU\Control Panel\International" /v sShortDate /t REG_SZ /d "%originalshortdate%" /f > nul