We often want to get the value for the day, month or year instead of the
complete date string.
To achieve this, we can choose between
FOR /F or SET's
substring functionality.
All following code assumes we got the values for Today and
Now using one of the techniques described before in
The Basics.
To use FOR /F we must know what delimiter is used.
For date values, either dash or forward slash is a safe guess:
FOR /F "tokens=1-3 delims=/-" %%A IN ("%Today%") DO (
SET DayMonth=%%A
SET MonthDay=%%B
SET Year=%%C
)
Now all we need to do is find out which value contains the day and which one the month.
There are two ways to find the date format used by the current user,
and thus the order of day and month: the DATE
command itself, or the registry.
The first is simpler, but still language dependent, the latter
is safer but more complex.
The DATE command displays the
date order when it prompts for input:
C:\>date
The current date is: 08-02-2012
Enter the new date: (dd-mm-yy)
Or:
C:\>date
The current date is: Wed 2/8/2012
Enter the new date: (m/d/yy)
The same string designating the order can be found in the registry value
HKEY_CURRENT_USER\Control \International\sShortDate.
Note that this string is still language dependent, as in Dutch
it will be dd-MM-jjjj, and in French it
will probably be something like jj-MM-aaaa.
Both designate the same order of day and month, but the strings are completely
different.
Only use this method if you are 100% certain of the system language.
If you are, you can use this technique to read and set the values in the correct order:
:: For REG.EXE 3.0 (Windows XP) and later versions
FOR /F "tokens=3" %%A IN ('REG QUERY "HKCU\Control Panel\International" /v sShortDate 2ˆ>NUL') DO (
SET sShortDate=%%A
)
:: For earlier REG.EXE versions
FOR /F "tokens=3" %%A IN ('REG QUERY "HKCU\Control Panel\International\sShortDate" 2ˆ>NUL') DO (
SET sShortDate=%%A
)
ECHO.%sShortDate% | FINDSTR /R /B /I /C:"dd*[-/]mm*[-/]yyyy$" >NUL
IF NOT ERRORLEVEL 1 (
SET Day=%%A
SET Month=%%B
SET Year=%%C
)
ECHO.%sShortDate% | FINDSTR /R /B /I /C:"mm*[-/]dd*[-/]yyyy$" >NUL
IF NOT ERRORLEVEL 1 (
SET Day=%%B
SET Month=%%A
SET Year=%%C
)
ECHO.%sShortDate% | FINDSTR /R /I /C:"yy*[-/]mm*[-/]dd" >NUL
IF NOT ERRORLEVEL 1 (
SET Day=%%C
SET Month=%%B
SET Year=%%A
)
A safer way is using the registry values iDate and
sDate for date values, and iDate and
sDate for time values.
These values can be found in
HKEY_CURRENT_USER\Control \International too.
The "s" in sDate and sTime stands for separator
(delimiter). The "i" in iDate and iTime probably stands
for international setting.
| Date/Time Format Settings | |||
|---|---|---|---|
| Name | 0 | 1 | 2 |
| iDate | MM/DD/YYYY | DD/MM/YYYY | YYYY/MM/DD |
| iTime | 12 hour clock | 24 hour clock | N/A |
| iTLZero | no leading zero (9:15) | leading zero (09:15) | N/A |
We can read the value of iDate using
REG.EXE, native as of Windows 2000,
or available for NT4 in one of the Resource Kits:
:: For REG.EXE 3.0 (Windows XP) and later versions
FOR /F "tokens=3" %%A IN ('REG QUERY "HKCU\Control Panel\International" /v iDate 2ˆ>NUL') DO (
SET iDate=%%A
)
:: For earlier REG.EXE versions
FOR /F "tokens=3" %%A IN ('REG QUERY "HKCU\Control Panel\International\iDate" 2ˆ>NUL') DO (
SET iDate=%%A
)
ECHO HKEY_CURRENT_USER\Control Panel\International\iDate=%iDate%
Using two similar REG commands makes sure that we
will get the required value, no matter which version of
REG.EXE is available.
| Date/Time Format Settings | |
|---|---|
| Name | Value |
| s1159 | AM or any other designation you choose for the morning (ignored if iTime = 1) |
| s2359 | PM or any other designation you choose for the afternoon (ignored if iTime = 1) |
| sDate | - or / or whatever date separator you choose |
| sTime | : or . or whatever time separator you choose |
The code to retrieve the value of sDate looks familiar:
:: For REG.EXE 3.0 (Windows XP) and later versions
FOR /F "tokens=3" %%A IN ('REG QUERY "HKCU\Control Panel\International" /v sDate 2ˆ>NUL') DO (
SET sDate=%%A
)
:: For earlier REG.EXE versions
FOR /F "tokens=3" %%A IN ('REG QUERY "HKCU\Control Panel\International\sDate" 2ˆ>NUL') DO (
SET sDate=%%A
)
ECHO HKEY_CURRENT_USER\Control Panel\International\sDate=%sDate%
Now let's build on what we found so far:
FOR /F "tokens=1-3 delims=%sDate%" %%A IN ("%Today%") DO (
IF "%iDate%"=="0" (
SET Day=%%B
SET Month=%%A
SET Year=%%C
)
IF "%iDate%"=="1" (
SET Day=%%A
SET Month=%%B
SET Year=%%C
)
IF "%iDate%"=="2" (
SET Day=%%C
SET Month=%%B
SET Year=%%A
)
)
| Note: | So far, I think this method and the
DEBUG RTC method are the only true
batch solutions that will give you 100% accuracy (unfortunately,
running DEBUG usually requires administrator privileges). It is possible to screw up the registry settings and break this method too, but that situation is highly unlikely! All other methods assume at least either a known day/month order or a known language. |
Parsing time values requires similar techniques.
For more details, have a look at my various versions of SortDate.bat
and SortTime.bat.
Often the date format will be known, at least partly.
We may know the order of day and month, but even then there may be
some systems that use leading zeroes, and others that don't.
Or we may be unsure of the separators used.
| Note: | In large networks it is advisable to use group policies to enforce a single enterprise wide standard date and time format. |
SET Now=%Time: =0% SET Hours=%Now:~0,2% SET Minutes=%Now:~3,2% ECHO.%Now% | FIND /I "P" >NUL && SET /A Hours += 12
Would fail for 12 hour clocks that do not use a "P" in their PM designation.
FOR /F "tokens=1,2 delims=:." %%A IN ("%Time%") DO (
SET /A Hours = 100%%A %% 100
SET /A Minutes = 100%%B %% 100
)
The code above would fail on 12 hour clocks with AM/PM designation appended to the minutes without a space, or on systems that use a different separator (not a dot nor a colon). Actually, this method ignores AM/PM completely.
FOR /F "tokens=1,2 delims=:." %%A IN ("%Time%") DO (
SET Hours=%%A
SET Minutes=%%B
)
SET /A Hours = 100%Hours% %% 100
ECHO.%Minutes% | FIND /I "P" >NUL && SET /A Hours += 12
SET Minutes=%Minutes:~0,2%
SET /A Minutes = 100%Minutes% %% 100
A little more code, and a little safer. Still, the code above would fail half the time for 12 hour clocks that do not use a "P" in their PM designation.
SET Today=%Date: =0% SET Year=%Today:~-4% SET Month=%Today:~-10,2% SET Day=%Today:~-7,2%
| Note: | Date parsing method by Ildar Shaimordanov. |
The code above would fail if the day does not have 2 digits.
A quick-and-really-dirty solution for that problem, not for
the faint of heart, could be:
SET Today=%Date: =0% SET Year=%Today:~-4% :: Include 1 extra character, which will be either a leading zero or a trailing separator SET Month=%Today:~-10,3% :: Remove separator SET Month=%Month:-=% SET Month=%Month:/=% :: Clear leading zeroes SET /A Month = 100%Month% %% 100 :: And add one again, if necessary SET /A Month = 100 + %Month% SET Month=%Month:~-2% SET Day=%Today:~-7,2% :: Remove separator SET Day=%Day:-=% SET Day=%Day:/=% :: Clear leading zeroes, as there may be 2 leading zeroes SET /A Day = 100%Day% %% 100 :: And add one again, if necessary SET /A Day = 100 + %Day% SET Day=%Day:~-2%
(I warned you it would get ugly...)
| page last uploaded: 4 March 2011, 12:50 |