2

The batch file is running robocopy and creating a log file of name robocopyServer_%date%.txt.

When the batch file is run manually, the result is robocopyServer_yyyy-mm-dd.txt

When the batch file runs from a scheduled task on Windows Server 2016, the result is robocopyServer_Tue (or whatever the day of the week is) and no file extension.

This batch file ran flawlessly on Windows Server 2012 R2 (manually or as scheduled task).

Mofi
  • 38,783
  • 14
  • 62
  • 115
TRex
  • 23
  • 1
  • 4
  • I'm not sure I have a workable answer. Unfortunately, my one and only Server 2016 machine just died (motherboard) so I cannot test. And I have not seen any ideas on why running the job manually differs from running it under Task Manager — which makes zero sense to me. – TRex Jun 23 '17 at 11:18
  • When I get the blasted machine back up and running, I'll check this. I *thought* I was running the scheduled task with the same userID, but possibly not. At least it gives me a plausible reason for the different behaviour between manual running and Scheduled Task running. Many thanks. – TRex Jun 26 '17 at 11:23
  • Possible duplicate of [How to get a UNIVERSAL Windows batch file timestamp](https://stackoverflow.com/questions/1747468/how-to-get-a-universal-windows-batch-file-timestamp) – phuclv Apr 16 '18 at 14:41

4 Answers4

6

%date% or date /t isn't always reliable as it depends on region and user settings. Here's how you can get a universally valid date:

for /f %%# in ('wmic os get localdatetime^|findstr .') do if "%%#" neq "" set date=%%#
set date=%date:~,4%-%date:~4,2%-%date:~6,2%
echo %date%

This will echo the current date in the yyyy-mm-dd format.

Regejok
  • 396
  • 1
  • 5
  • 1
    You should not assign anything to a variable called `date`, because this is a built-in dynamic variable, which can no longer be accessed; you should use a different name for your variable instead... – aschipfl Jun 21 '17 at 15:20
  • Since it is a server where I've set the region date settings (yyyy-mm-dd), it should not be necessary to go through a lot of hoops just to get the date. I don't understand why having it run from Scheduled Tasks should produce a different result than when it is run manually. – TRex Jun 22 '17 at 14:53
1

The format of the strings of the environment variables DATE and TIME depends on Windows region settings as defined for used account, i.e. which country is configured for the account used on running the batch file because the country determines the date and time format.

A region independent date/time string can be get using Windows Management Instrumentation Command line tool WMIC.

The command line

wmic OS GET LocalDateTime /VALUE

outputs UTF-16 Little Endian encoded for example:

 
 
LocalDateTime=20170621095402.953000+120
 
 

There are two empty lines, then the line with the current local date/time in format yyyyMMddHHmmss.microsecond±UTC offset in minutes and two more empty lines.

These data can be used with a batch code like this:

@echo off
for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "FileNameDate=%%I"
set "FileNameDate=%FileNameDate:~0,4%-%FileNameDate:~4,2%-%FileNameDate:~6,2%"
echo %FileNameDate%

Of interest for file and folder names is only the date/time string between the equal sign and the decimal point which is the reason for using for /F options tokens=2 delims==. to get just 20170621095402 assigned to loop variable I whose value is assigned next to environment variable FileNameDate.

The environment variable FileNameDate is reformatted using string substitutions to get just the date string in format yyyy-MM-dd which is output for verification resulting in the output 2017-06-21.

The advantage of using WMIC to get local date/time is being independent on Windows region settings. The disadvantage is that the command execution takes a quite long time (1 to 2 seconds) in comparison to the usage of the DATE and TIME environment variables which are accessed in a few microseconds.

The command FOR has problems parsing Unicode output correct. It interprets the byte sequence 0D 00 0A 00 0D 00 0A 00 at end of the WMIC output because of the two empty lines as 0D 0D 0A, i.e. as two carriage returns and one line-feed. This results in interpreting the last two empty lines at end of WMIC output as a single line with a single carriage return as string.

That is very often a problem because the result of set "EnvironmentVariable=%%I" is with %%I expanding to just carriage return in deleting the environment variable already defined before with the correct value.

There are multiple solutions to work around this Unicode parsing error of command FOR. It is possible to append & goto Label to exit the loop with a jump to :Label below the FOR loop once the value is assigned to the environment variable to avoid running into this problem at all.

Another solution is the one used in this code. Because of using WMIC option /VALUE the name of the property and its value are output on same line. The command FOR runs the command SET because of tokens=2 only when it could split up the current line into at least 2 substrings (tokens) using equal sign and dot as delimiters because of delims==.. But the wrong parsed end of WMIC output is for FOR a line containing only a carriage return and therefore has no second token. For that reason the wrongly parsed empty lines are also ignored here by the command FOR.

See How to correct variable overwriting misbehavior when parsing output? and cmd is somehow writing Chinese text as output for details on parsing problem of FOR on UTF-16 LE encoded output.

For understanding the used commands and how they work, open a command prompt window, execute there the following commands, and read entirely all help pages displayed for each command very carefully.

  • echo /?
  • for /?
  • set /?
  • wmic /?
  • wmic os /?
  • wmic os get /?
  • wmic os get localdatetime /?

PS: There are lots of other solutions to get current date/time in a specific format independent on country configured for used account. Some of them are faster than the usage of wmic. All those alternative solutions can be found in the answers on:

How do I get current date/time on the Windows command line in a suitable format for usage in a file/folder name?

Mofi
  • 38,783
  • 14
  • 62
  • 115
1

You have to create a Windows profile for the user being used to run the Task and configure the Regional Settings and Date format under that profile.

robinCTS
  • 5,458
  • 14
  • 27
  • 37
SHADES_77
  • 11
  • 1
0

I had a similar issue as the OP and I love the method using wmic @Regejok. Here is my solution to handle unique strings returned by DOS DATE (U.S. solution - sorry no other region OS to test with but this can be refactored pretty quickly for other regions).

I had servers that were returning different strings for %DATE% (date /t).

ex. 1 - Wed 07/04/2018 (perfectly fine string)

ex. 2 - 07/04/2018 (another perfectly fine string but failed my batch script because of sub-string referencing)

I was using this script selecting substrings from DATE & TIME to create date/timestamp vars for logging & archiving files:

ORIGINAL SCRIPT

@echo off
set HH=%TIME:~0,1%
if "%HH%"==" " goto addzero
goto hourOK
:addzero
set HH=0%TIME:~1,1%
goto end
:hourOK
set HH=%TIME:~0,2%
:end

set mn=%TIME:~3,2%
set SS=%TIME:~6,2%
set ms=%TIME:~9,2%
set MM=%DATE:~4,2%
set DD=%DATE:~7,2%
set YY=%DATE:~-2%
set CCYY=%DATE:~-4%
set dts=%CCYY%%MM%%DD%%HH%%mn%%SS%%ms%
set dateonly=%CCYY%%MM%%DD%
set monthlog=%CCYY%%MM%
@echo on

Please don't judge the code. :) It gets better.

RESULTS FOR 'Wed 07/04/2018':

C:\>set HH=
C:\>if " " == " " goto addzero
C:\>set HH=09
C:\>goto end
C:\>set mn=30
C:\>set SS=49
C:\>set ms=69
C:\>set MM=07
C:\>set DD=04
C:\>set YY=18
C:\>set CCYY=2018
C:\>set dts=2018070409304969
C:\>set dateonly=20180704
C:\>set monthlog=201807

This worked great with the ex. 1 string. I skipped over the abbreviated day (Wed) and all was well. Until I hit a server that returned ex. 2.

FAILED RESULTS FOR '07/04/2018':

C:\>set HH=
C:\>if " " == " " goto addzero
C:\>set HH=09
C:\>goto end
C:\>set mn=31
C:\>set SS=48
C:\>set ms=59
C:\>set MM=4/
C:\>set DD=01
C:\>set YY=18
C:\>set CCYY=2018
C:\>set dts=20184/0109314859
C:\>set dateonly=20184/01
C:\>set monthlog=20184/

All the date/timestamps contained a '/' (fail for file naming). This is all due to the DATE string difference and the sub-string references. The TIME was fine. Even with the failure in the month (MM) and the day (DD) strings I noticed the 2-digit and 4-digit year vars were fine (YY & CCYY). How? Negative referencing. This became the biggest fix to my final script. Along with string replacement.

MY NEW SCRIPT (I still love the method using wmic, this is just an alternate way allowing the 2 different return types for DATE using DOS only)

01  @echo off
02  set str=%DATE%      
03  set str=%str:/=%     
04 
05  set MM=%str:~-8,2%  
06  set DD=%str:~-6,2%  
07  set YY=%str:~-2%    
08  set CCYY=%str:~-4%  
09
10  set HH=%TIME:~0,2%  
11  set HH=%HH: =0%     
12  set mn=%TIME:~3,2%  
13  set SS=%TIME:~6,2%  
14  set ms=%TIME:~9,2%  
15
16  set _dts=%CCYY%%MM%%DD%%HH%%mn%%SS%%ms%
17  set _dateonly=%CCYY%%MM%%DD%
18  set _monthlog=%CCYY%%MM%
19  @echo on

NOTES:

line 2:

'str' var holds the value returned from DATE. 
Could be formatted like ex. 1 or ex. 2, does not matter

line 3:

this is string replacement, all '/' replaced with '' (null). 
ex. 1 - 'Wed 07/04/2018' >> 'Wed 07042018', ex. 2 - '07/04/2018' >> '07042018'

line 5:

this is where negative referencing made both date strings equal (in a sense), 
month (MM) starts at '-8' characters from the end of the string in both 
examples, length of '2'

line 6:

Same with day (DD), '-6' characters from end of string, length of '2'

line 7:

2-digit year (YY) works as it did before (already used negative referencing)

line 8:

4-digit year (CCYY) works as it did before as well

line 10:

TIME always returns 2-digits in its hour (HH) position, it just doesn't have
a leading '0' if less than 10, what it does return is a leading space 
i.e. %TIME:~0,2% will return ' 9' for 9:00 AM (not desired for date/timestamps)

line 11:

string replacement to the rescue again, replace all spaces with '0', 
turns the ' 9' to '09' (exactly what we want)

line 12:

minutes, seconds, milliseconds all work as they did previously, using 
sub-strings to avoid the colons (':') & the period ('.') in the time stamp 
i.e. 10:01:26.29

RESULTS FROM NEW SCRIPT:

C:\>set str=07/04/2018
C:\>set str=07042018
C:\>set MM=07
C:\>set DD=04
C:\>set YY=18
C:\>set CCYY=2018
C:\>set HH= 9
C:\>set HH=09
C:\>set mn=42
C:\>set SS=26
C:\>set ms=48
C:\>set _dts=2018070409422648
C:\>set _dateonly=20180704
C:\>set _monthlog=201807


C:\>set str=Wed 07/04/2018
C:\>set str=Wed 07042018
C:\>set MM=07
C:\>set DD=04
C:\>set YY=18
C:\>set CCYY=2018
C:\>set HH=10
C:\>set HH=10
C:\>set mn=50
C:\>set SS=55
C:\>set ms=48
C:\>set dts=2018070410505548
C:\>set dateonly=20180704
C:\>set monthlog=201807

Hope this helps. It is not unique or earth shattering, just another way.