StrToDateTime("2009-07-02 11:23:11"); 이 에러나는 경우
혹시 다음과 같이 StrToDateTime 함수를 쓰면서
에러가 나는 경우를 격어 보신적 있으신가요?
void __fastcall TForm1::Button2Click(TObject *Sender)
{
TDateTime dt=StrToDateTime("2009-07-02 11:23:11");
}
//---------------------------------------------------------------------------
아무리 봐도 전혀 문제가 전혀 문제가 없는 코드 같지 않나요?
예전에 그런 경험을 한적이 있었는데..
대부분의 pc에서는 아무 문제가 없는데..
특정 pc에서 예외를 발생시키더군요
왜그럴까요?
그것은 윈도우즈의 시스템 설정이 다른기 때문입니다.
"제어판" "국가 및 언어 옵션" 에서 숫자,통화,시간,날짜 등의 형식을 사용자 지정할수가 있는데..
이것을 사람마다 다르게 해 놓고 쓰는경우가 가끔 있더군요
특히나 만약 해외로 프로그램을 만들어 판다면
이런 사항은 반드시 고려해야할 사항이라 할수 있겠죠
제어판의 사용자 지정 날짜 Format을 프로그램에 적용하려면?
그럼 위 그림의 제어판 국가별 옵션 설정을 어떻게 프로그램에 적용할수 있을까요?
간단합니다
String이용하지 않고
DateUtils유닛에 있는 EncodeDateTime 함수를 사용하면 됩니다
#include "DateUtils.hpp"
void __fastcall TForm1::Button3Click(TObject *Sender)
{
TDateTime dt=EncodeDateTime(2009,07,02,11,23,11,0);
ShowMessage(dt.DateTimeString());
}
//---------------------------------------------------------------------------
제어판의 사용자 지정 날짜 Format에 관계없이 쓰려면?
그런데 반대로 위 제어판 옵션을 무시하고 항상 특정한 Format으로 나오게 하고 싶은경우는 어떻게 하면 될까요?
SysUtils에 보니 다음과 같은 global 변수들이 있네요
extern PACKAGE AnsiString CurrencyString;
extern PACKAGE Byte CurrencyFormat;
extern PACKAGE Byte NegCurrFormat;
extern PACKAGE char ThousandSeparator;
extern PACKAGE char DecimalSeparator;
extern PACKAGE Byte CurrencyDecimals;
extern PACKAGE char DateSeparator;
extern PACKAGE AnsiString ShortDateFormat;
extern PACKAGE AnsiString LongDateFormat;
extern PACKAGE char TimeSeparator;
extern PACKAGE AnsiString TimeAMString;
extern PACKAGE AnsiString TimePMString;
extern PACKAGE AnsiString ShortTimeFormat;
extern PACKAGE AnsiString LongTimeFormat;
extern PACKAGE AnsiString ShortMonthNames[12];
extern PACKAGE AnsiString LongMonthNames[12];
extern PACKAGE AnsiString ShortDayNames[7];
extern PACKAGE AnsiString LongDayNames[7];
다음과 같이 SysUtils의 내용을 ShowMessage로 뿌려봤습니다.
void __fastcall TForm1::Button4Click(TObject *Sender)
{
TStringList *lst=new TStringList;
lst->Add("CurrencyFormat="+ String(CurrencyFormat));
lst->Add("NegCurrFormat="+ String(NegCurrFormat));
lst->Add("ThousandSeparator="+ String(ThousandSeparator));
lst->Add("DecimalSeparator="+ String(DecimalSeparator));
lst->Add("CurrencyDecimals="+ String(CurrencyDecimals));
lst->Add("DateSeparator="+ String(DateSeparator));
lst->Add("ShortDateFormat="+ ShortDateFormat);
lst->Add("LongDateFormat="+ LongDateFormat);
lst->Add("TimeSeparator="+ String(TimeSeparator));
lst->Add("TimeAMString="+ TimeAMString);
lst->Add("TimePMString="+ TimePMString);
lst->Add("ShortTimeFormat="+ ShortTimeFormat);
lst->Add("LongTimeFormat="+ LongTimeFormat);
for(int i=0;i<12;i++)
lst->Add("ShortMonthNames["+IntToStr(i)+"]="+ShortMonthNames[i]);
for(int i=0;i<12;i++)
lst->Add("LongMonthNames["+IntToStr(i)+"]="+ LongMonthNames[i]);
for(int i=0;i<7;i++)
lst->Add("ShortDayNames["+IntToStr(i)+"]="+ ShortDayNames[i]);
for(int i=0;i<7;i++)
lst->Add("LongDayNames["+IntToStr(i)+"]="+ LongDayNames[i]);
ShowMessage(lst->Text);
delete lst;
}
//---------------------------------------------------------------------------
다음과 같이 나오네요
정리하면
extern PACKAGE AnsiString CurrencyString;
extern PACKAGE Byte CurrencyFormat;
extern PACKAGE Byte NegCurrFormat;
extern PACKAGE char ThousandSeparator; //천단위 구분문자
extern PACKAGE char DecimalSeparator; //소숫점 구분문자
extern PACKAGE Byte CurrencyDecimals;
extern PACKAGE char DateSeparator; //날짜 구분문자
extern PACKAGE AnsiString ShortDateFormat; //짧은 날짜 형식
extern PACKAGE AnsiString LongDateFormat; //긴 날짜 형식
extern PACKAGE char TimeSeparator; //시간 구분문자
extern PACKAGE AnsiString TimeAMString; //오전을 나타내는 String
extern PACKAGE AnsiString TimePMString; //오후를 나타내는 String
extern PACKAGE AnsiString ShortTimeFormat; //짧은 시간 형식
extern PACKAGE AnsiString LongTimeFormat; //긴 시간 형식
extern PACKAGE AnsiString ShortMonthNames[12]; //1월~12월까지 짧은 표현형식
extern PACKAGE AnsiString LongMonthNames[12]; //1월~12월까지 긴 표현형식
extern PACKAGE AnsiString ShortDayNames[7]; //일요일~토요일까지 짧은 표현형식
extern PACKAGE AnsiString LongDayNames[7]; //일요일~토요일까지 긴 표현형식
위에 global변수는 프로그램이 시작할때
그리나까 VCLxx.bpl이 Load될때 System에서 정보를 가져와서 셋팅합니다.
그런후에 StrToDateTime 같은 함수에서 위 변수에 내용을 참조해서 적용하는것 입니다.
결론적으로
제어판의 사용자 지정 날짜 Format에 관계없이 쓰려면
위 SysUtils의 내용을 임의대로 바꾸어 쓰면 됩니다.
다음과 같이..
void __fastcall TForm1::Button2Click(TObject *Sender)
{
char OrgDateSeparator,OrgTimeSeparator;
OrgDateSeparator=DateSeparator;
OrgTimeSeparator=TimeSeparator;
DateSeparator='*';
TimeSeparator='^';
TDateTime dt=StrToDateTime("2009*07*02 11^23^11");
DateSeparator=OrgDateSeparator;
TimeSeparator=OrgTimeSeparator;
ShowMessage(dt.DateTimeString());
}
//---------------------------------------------------------------------------
날짜 구분자뿐 아니라 순서도 바뀌는 경우에도
ShortDateFormat 또는 LongDateFormat을 수정해서 적용할수 있습니다.
void __fastcall TForm1::Button5Click(TObject *Sender)
{
char OrgDateSeparator,OrgTimeSeparator;
OrgDateSeparator=DateSeparator;
OrgTimeSeparator=TimeSeparator;
String sOrg=ShortDateFormat;
ShortDateFormat="dd-mm-hhhh hh:nn:ss";
DateSeparator='*';
TimeSeparator='^';
TDateTime dt=StrToDateTime("02*07*2009 11^23^11");
DateSeparator=OrgDateSeparator;
TimeSeparator=OrgTimeSeparator;
ShortDateFormat=sOrg;
ShowMessage(dt.DateTimeString());
}
//---------------------------------------------------------------------------
이것도 뭐 모른다고 해서
큰 문제될것 없는데...
좀더 완성도 높은 프로그램을 위해..
GLOBAL한 프로그램을 위해...
그럼..
'dd-mm-yyyy hh:nn' 이런 식으로 완전히 틀리게 사용하는 경우도 있는거 같네요. ^^;;
이런 경우는 어떻게 하나요?