Microsoft MVP성태의 닷넷 이야기
VC++: 19. 다국어 지원: setlocale( LC_TIME, "" ) 관련 [링크 복사], [링크+제목 복사],
조회: 27029
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

이번엔, 어떤 분이 질문한 것에 대한 답변을 올려 봅니다. 메일에 대한 답변이었기 때문에, 맨 아래의 질문 메일 내용을 먼저 읽어주세요. ^^

멀리서... 저까지 찾아주시다니.... ^^ 감사할 따름입니다. 답변이 늦어서,,, 이미 해결을 하셨는지 모르겠지만. ^^

우선, 저도 정확한 답변은 드릴 수 없습니다. 왜냐면, 다양한 클라이언트의 환경에서 테스트를 해보아야 하고, 그러한 문제를 가진 컴퓨터에서 해봐야 하는 경우도 있기 때문에 장담할 수 없습니다.

사실... ^^; 더 정확한 이유는... 저 역시 간간이 다국어에 대한 지식만을 습득했을 뿐, 제대로 된 다국어 프로젝트를 진행해 본 적이 한번도 없습니다.
따라서... 그냥 경험상으로 아는 사실만 나열해 보겠습니다.


일단... setlocale 함수에서 두 번째 인자를 ""로 주는 것은 해당 시스템에 설정된 "regional settings"를 그대로 받겠다는 의미입니다.  MSDN 도움말에서의 표현을 빌리자면 "user-default ANSI code page obtained from the operating system"인 것이죠.


 
 
위의 화면에서 보는 것처럼... (일본어 판 윈도우즈입니다.) regional options의 기본적으로 사용될 region 세팅을 할 수가 있습니다. 이 때 설정한 값이 바로  setlocale( LC_TIMIE, "" );와 같이 두 번째 인자의 ""가 쓰일 때 대신 사용될 region입니다.
 
위의 예제는 일본어판 윈도우즈에서 "한국어"를 지정한 것입니다.
위에서 "한국어"를 지정하는 것과 "일본어"를 지정하는 것은
을 가보면 쉽게 알 수 있습니다 지정된 언어에 따라 일본어인 경우에는 www.msn.co.jp로 가고,
한국어인 경우에는 www.msn.co.kr로 갑니다.

^^ 다 아시는 내용이겠지만.

본격적으로 질문에 답을 하자면.

"Lee" 님이 지금 겪고 있는 문제는 바로... "일본어" 윈도우즈에서 "한국어" 설정을 한 경우와 비슷한 상황에서 나타나는" 것으로 보입니다."
그렇게 되면,,,
 
TCHAR *ptr = _tsetlocale(LC_TIME, _T(""));
 
에서 ptr == "Korean_Korea.949"가 나오게 되고, CTime.Format 결과는 아래와 같이 깨진 문자열이 나오게 됩니다.
 
 
 
그런데... 왜 깨지느냐...를 물으시는 건데요.
 
그건 바로, setlocale의 LC_TIME 인자에 원인이 있습니다. 즉... 해당 인자의 의미는 DATETIME 부분만 region 설정을 할 뿐, 그 외의 설정은 한국어가 아니기 때문에 나타납니다. 즉 이후의 (CTime.Format 내부에서 호출되는) "wcsftime" 등에서 날짜 처리 부분만 "Korean" 지역 설정이 되고 나머지 문자열 처리에서는 ANSI 설정이 그대로 들어가기 때문에 나타납니다.
(기본적으로 프로그램은 시작시에 setlocal( LC_ALL, "C") 설정이 들어간 것과 같다고 MSDN 도움말에 나옵니다.)
 
따라서... LC_TIME 에만 setlocale( LC_TIME, 'Korean" ); 적용이 되어 있고, 나머지 모든 처리는 setlocale( LC_ALL, "C" );를 기반으로 하기 때문에 문자열이 깨지는 것입니다.
 
너무 어렵게 돌아왔나요.... ^^;
답은 setlocale( LC_ALL, "" );이라고 설정하시면 해결됩니다.
 
물론, TCHAR은 wchar_t로 처리되도록 "#define _UNICODE"라고 되어 있어야 하지요. ^^


-----Original Message-----
From: XXXXXXXXXXXXXX
Sent: Friday, October 21, 2005 6:07 AM
To: 정성태
Subject: Help about CTime::Format() function

안녕하세요, 정성태님.
이렇게 무례하게 이메일드려 죄송합니다. 저는 미국에서 소프트웨어를 개발하고 있는 XXX이라고 합니다.
다름이 아니오라, VC7를 사용하고있는데요.
저희제품은 UNICODE를 사용하기 때문에 char 대신에 wchar_t 혹은 TCHAR 를 사용합니다. 제가 질문하고자 하는것은, CTime 클래스를 이용하여 longdate 포맷을 하려고 하는데, 물론 서양 환경 (SBCS) 에서는 문제없이 날짜/시간 포맷이 잘되는데, 한글환경에서는 문제가 있다는게 발견 되어서 제가 그것을 고치려다보니까, 어쩔수없이 이처럼 무례를 범하게 되었습니다.

현재 문제가 제기된 함수에서 아래와 같이 시간을 format 하고있습니다.

CTime time(0);
TCHAR *ptr = _tsetlocale(LC_TIME, _T("")); CString strTmp = time.Format("%#x  %X");

MSDN 에 따른다면,
strTmp = "Wednesday, December 31, 1969 19:00:00" (사용자 locale이 English일 경우) strTmp = "1969년 12월31일 수요일 오후 7:00:00" (사용자 locale이 한글일 경우) 가 되어야 하는데, 실제 어떤 컴퓨터에서는 strTmp = "1969? 12?31? ??? ?? 7:00:00"
또 다른 컴퓨터에서는
strTmp = "1969³â 12¿ù 31ÀÏ ¼ö¿äÀÏ  ¿ÀÈÄ 7:00:00"
이렇게 나오거든요.

그래서 결국은 제가 아래와 같이 바꿨습니다.

CTime time(0);

SYSTEMTIME tm;
time.GetAsSystemTime(tm);
_TCHAR szDate[100], szTime [100];
GetDateFormat( LOCALE_USER_DEFAULT, DATE_LONGDATE, &tm, NULL, szDate, sizeof( szDate )/sizeof( _TCHAR )); GetTimeFormat( LOCALE_USER_DEFAULT, LOCALE_NOUSEROVERRIDE, &tm, NULL, szTime, sizeof( szTime )/sizeof( _TCHAR )); CString strDateTime = (CString)szDate + _T(" ") + (CString) szTime;

보시다시피, 깨끗해보였던 코드가 아주 지저분해졌답니다.
일단은 제가 팀원들한테 VC 버그라고했는데, 과연 VC버그인지 혹은 제가 무지해서 그런지 알고싶어서 연락드리는 바입니다.

감사합니다.







[최초 등록일: ]
[최종 수정일: 7/9/2021]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2025-02-11 10시55분
The default C locale is not a very interesting one
; https://devblogs.microsoft.com/oldnewthing/20250206-00/?p=110846

wchar_t example[] = L"\x00C0" L"BC"; // ÀBC
_wcslwr_s(example); // Result: Àbc

Using alternate locales to get more interesting case mapping than the C
; https://devblogs.microsoft.com/oldnewthing/20250207-00/?p=110848

// Set the C runtime locale for character
// classification (which includes case mapping)
// to the user's default locale
_wsetlocale(LC_CTYPE, L"");

// Now you can convert to lowercase in a locale-aware manner
wchar_t example[] = L"\x00C0" L"BC"; // ÀBC
_wcslwr_s(example); // Result: probably àbc
정성태

... 61  [62]  63  64  65  66  67  68  69  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12389정성태11/1/202018753.NET Framework: 958. C# 9.0 - (8) 정적 익명 함수 (static anonymous functions)파일 다운로드1
12388정성태10/29/202017761오류 유형: 674. 어느 순간부터 닷넷 응용 프로그램 실행 시 System.Configuration.ConfigurationErrorsException 예외가 발생한다면?
12387정성태10/28/202018553.NET Framework: 957. C# - static 필드의 정보가 GC Heap에 저장될까요? [3]파일 다운로드1
12386정성태10/28/202019301Linux: 34. 사용자 정보를 함께 출력하는 리눅스의 ps 명령어 사용 방법
12385정성태10/28/202016652오류 유형: 673. openssl - req: No value provided for Subject Attribute CN, skipped
12384정성태10/27/202018989오류 유형: 672. AllowPartiallyTrustedCallers 특성이 적용된 어셈블리의 struct 멤버 메서드를 재정의하면 System.Security.VerificationException 예외 발생
12383정성태10/27/202019066.NET Framework: 956. C# 9.0 - (7) 패턴 일치 개선 사항(Pattern matching enhancements) [3]파일 다운로드1
12382정성태10/26/202016823오류 유형: 671. dotnet build - The local source '...' doesn't exist
12381정성태10/26/202018803VC++: 137. C++ stl map의 사용자 정의 타입을 key로 사용하는 방법 [1]파일 다운로드1
12380정성태10/26/202014747오류 유형: 670. Visual Studio - Squash_FailureCommitsReset
12379정성태10/21/202020355.NET Framework: 955. .NET 메서드의 Signature 바이트 코드 분석 [1]파일 다운로드2
12378정성태10/15/202019302.NET Framework: 954. C# - x86/x64 환경에 따라 달라지는 P/Invoke 함수의 export 이름 [1]파일 다운로드1
12377정성태10/15/202019743디버깅 기술: 172. windbg - 파일 열기 시점에 bp를 걸어 파일명 알아내는 방법(Managed/Unmanaged)
12376정성태10/15/202015844오류 유형: 669. windbg - sos의 name2ee 명령어 실행 시 "Failed to request module list." 오류
12375정성태10/15/202017356Windows: 177. 윈도우 탐색기에서 띄우는 cmd.exe 창의 디렉터리 구분 문자가 'Yen(¥)' 기호로 나오는 경우 [1]
12374정성태10/14/202023247.NET Framework: 953. C# 9.0 - (6) 함수 포인터(Function pointers) [1]파일 다운로드2
12373정성태10/14/202017005.NET Framework: 952. OpCodes.Box와 관련해 IL 형식으로 직접 코딩 시 유의할 점
12372정성태10/13/202019421.NET Framework: 951. C# 9.0 - (5) 로컬 함수에 특성 지정 가능(Attributes on local functions)파일 다운로드1
12371정성태10/13/202018302개발 환경 구성: 519. Visual Studio의 Ctrl+Shift+U (Edit.MakeUppercase) 단축키가 동작하지 않는 경우
12370정성태10/13/202018519Linux: 33. Linux - nmcli를 이용한 고정 IP 설정
12369정성태10/12/202022163Windows: 176. Raymond Chen이 한글날에 밝히는 윈도우의 한글 자모 분리 현상 [3]
12368정성태10/12/202018305오류 유형: 668. VSIX 확장 빌드 - The "GetDeploymentPathFromVsixManifest" task failed unexpectedly.
12367정성태10/12/202030778오류 유형: 667. Ubuntu - Temporary failure resolving 'kr.archive.ubuntu.com' [2]
12366정성태10/12/202020132.NET Framework: 950. C# 9.0 - (4) 원시 크기 정수(Native ints) [1]파일 다운로드1
12365정성태10/12/202018468.NET Framework: 949. C# 9.0 - (3) 람다 메서드의 매개 변수 무시(Lambda discard parameters)파일 다운로드1
12364정성태10/11/202019465.NET Framework: 948. C# 9.0 - (2) localsinit 플래그 내보내기 무시(Suppress emitting localsinit flag)파일 다운로드1
... 61  [62]  63  64  65  66  67  68  69  70  71  72  73  74  75  ...