by Michael S. Kaplan, published on 2007/04/21 03:43 -04:00, original URI: http://blogs.msdn.com/b/michkap/archive/2007/04/21/2222812.aspx
The question that was asked to the popular alias about Win32 development:
We’ve got a stubborn machine on which a CMD window opened by the user emits date /t as “Thu 04/19/2007” whereas when Visual Studio 2005 runs a .cmd file from a build-step, date /t emits “04/19/2007 Thu”. The displaced tokens interfere with the parsing rules in the .cmd.
I’m looking for some kind of “mode cp” command or something that we can push/pop in the .cmd file to ensure date/time is presented in a known, fixed format.
We’re also wondering why the Control Panel Regional Settings applet does not seem to be effecting the DOS-box (perhaps we just don’t realize when a reboot is required or something)? And why does VS2k5 use a different cmd environment than the interactive user (who launched VS2k5)?
Thanks
Funny story about this one....
Well, actually, not so much a story as several longstanding behaviors, each of which when taken on its own might be okay but then when you combine them all together turn into something really hard to do much more than shake one's head, let alone fathom.
We start with the day names -- these are loaded when CMD starts, along with some other trivia about separators and such. Those day names are the ones that get inserted somewhere in the string later with that date command. Well, sometimes.
Then we'll talk about how it gets the date format to use. It calls GetDateFormat, using as an LCID... wait for it... LOCALE_USER_DEFAULT.
Each time.
Yes, that means that if you change your user locale, it will pick up the changes in regard to your preferred short date format, even though the day name it uses may well not match that locale....
Luckily it is just a short date, but the fact that there are no month names in there is more a convention in the data than a rule. If you are unlucky enough, you might find some very odd results with mixed languages in the string....
But wait, it gets better.
You see, starting in Vista it actually doesn't use LOCALE_USER_DEFAULT; it uses a wrapper around GetUserDefaultLCID to make sure that if you are using a complex script locale as your default user locale that it can give you a fallback that will work in the console.
Unfortunately, the wrapper is not using the new LOCALE_SCONSOLEFALLBACKNAME of GetLocaleInfoEx, also added in Vista, for this very situation.
Instead, it is just checking if PRIMARYLANGID(GetUserDefaultLCID) returns LANG_ARABIC, LANG_HEBREW, LANG_THAI, LANG_HINDI, LANG_TAMIL, or LANG_FARSI.
Unfortunately this ignores the possibility of it being LANG_DIVEHI, LANG_GUJARATI, LANG_KANNADA, LANG_KHMER, LANG_LAO, LANG_MALAYALAM, LANG_MARATHI, LANG_NEPALI, LANG_ORIYA, LANG_PASHTO, LANG_PUNJABI, LANG_SANSKRIT, LANG_SINHALESE, LANG_SYRIAC, LANG_TELUGU, LANG_TIBETAN, LANG_UIGHUR, LANG_URDU, or any of the others I may have forgotten.
Even more unfortunately, it ignores the possibility of it being a custom locale supporting any of these or indeed any other complex script locale.
But wait, it gets worse.
The way that the determination is made for whether the day name comes before or after the date is essentially taking a look at the return of GetConsoleOutputCP and whether it returns 932, 936, 949, or 950. In other words whether it is a CJK double-byte code page. This is another setting that can be changed with a chcp call....
(there is some other trivia involved in the decision like whether the day name is in the string already and such, to avoid the potentially embarrassing stutter of repeating the name, I guess.
Because I'm sure that is the only possible behavior in all that I have described that folks might find embarrassing? :-)
In any case, I am not entirely sure what VS 2005 is doing here, but it is clear that relying on the hard-coded nature of date is going to be a pretty bug mistake. Much safer if you want a date that is going to vary to generate it yourself with your own tool.
I'll talk to some people 'bout the clean-up the CMD behavior for the next version of Windows. :-)
This post brought to you by ၎ (U+104e, a.k.a. MYANMAR SYMBOL AFOREMENTIONED)