一个变态问题的解决!!!!!!!!!(时间)

来源:互联网 发布:关于的淘宝图片 编辑:程序博客网 时间:2024/05/17 01:17
 向数据库插入一条记录,其中有datetime数据,在某个机上no problem,但是在另一机上,出错,提示:字符串在向datetime转换时要截断字符。
问题:出错机上的时间格式虽然是24小时制的,但是是上下午制,即
2006-11-1 上午 11:22:22(不明白这种格式为什么也是24小时制。)
而数据库的时间格式是
2006-11-1 11:22:22,
所以错了。
解决1:从程序里获取时间时,也作格式转换,因为系统时间是第一种格式的,所以程序里获取的时间也是第一种格式的,
参考:

Delphi获得与设置系统时间格式

在Delphi中,特别是在写管理系统软件时,经常要用到 FormatDateTime 以将 TDateTime 格式的日期时间转换成字符串形式的值显示或保存起来,或者用 StrToDateTime将字符串形式的日期时间转换成 TDateTime 然后再做其他操作。
在进行时间或日期的转换时,会使用系统当前设定的时间日期格式。而如果时间日期格式与字符串中的表示方式 不相符,会使转换过程失败。例如当前短日期格式设定为'yyyy/MM/dd',而要转为 '2006-10-20'这样的字符串为日期,就会报错,说这不是一个有效的日期。
所以在进行转换前,要确保系统的日期时间格式与程序中使用的相符。一种方法是在安装时由安装程序设置,或者明确告诉用户必须设置成要求格式。另一种就是程序在启动时,自动设定为需要的格式,退出程序时再恢复原来的设置。
需要用到的有两个Windows API,一个是 GetLocaleInfo,一个是 SetLocaleInfo。
查API说明:
int GetLocaleInfo(
    LCID Locale, // locale identifier ,设置信息的范围,是系统级,还是当前用户
    LCTYPE LCType, // type of information,设置信息的类型
    LPTSTR lpLCData, // address of buffer for information,设置成的值,必须用 pchar的格式传进去
    int cchData  // size of buffer
   );

BOOL SetLocaleInfo(
    LCID Locale, // locale identifier,同上
    LCTYPE LCType, // type of information to set
    LPCTSTR lpLCData  // pointer to information to set
   );

两 个函数的参数很类似,其中 Locale可以取两个值:LOCALE_SYSTEM_DEFAULT,表示要操作的是系统默认的设置; LOCALE_USER_DEFAULT,表示要操作的是当前用户的设置。还可以取其他值,用于具体修改某种语言区域的设置。一般取 LOCALE_USER_DEFAULT。
LCType,表示要操作信息的类型,也就是要操作的是哪一种设置。可用的值有很多,Delphi的联机帮助,或者查MSDN,都有一个大列表。但跟日期时间格式相关的一共有这几个:
LOCALE_SSHORTDATE :短日期格式
LOCALE_SLONGDATE :长日期格式
LOCALE_STIMEFORMAT:时间格式
另外 LOCALE_STIME 表示时间分隔符,LOCALE_SDATE 表示日期分隔符。可以单独使用,也可以在使用 LOCALE_SSHORTDATE 和 LOCALE_STIMEFORMAT 的同时一并修改,所以不需要单独操作。
使用GetLocaleInfo或SetLocaleInfo时,每次只能操作一个类型。比如要同时设置短日期格式、长日期格式、时间格式,就必须分别用三个类型代号调用三次 SetLocaleInfo。
还要一个要注意的问题是,设置日期时间格式后,应该向当前系统的激活窗口广播发送 WM_SETTINGCHANGE 消息,否则即使修改了,程序里还是不能用的。
以下是获取和设置的程序片断。

1.//获取时间日期格式

procedure GetDateTimeFormat();
var
  buf:pchar;
  i:integer;
  GPrevShortDate,GPrevLongDate,GPrevTimeFormat:string;
begin
  getmem(buf,100);
  i:=100; //i必须在调用前赋值为buf缓冲区的长度。如果设为0或负值,将取不到设置的值
  GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SSHORTDATE,buf,i); //取当前用户设置,短日期格式。
  GPrevShortDate:=string(buf);
  i:=100;
  GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SLONGDATE,buf,i); //取长日期格式
  GPrevLongDate:=string(buf);
  i:=100;
  GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_STIMEFORMAT,buf,i); //取时间格式
  GPrevTimeFormat:=string(buf);
  FreeMem(buf);
end;

 

2.//设置时间格式
procedure SetDateTimeFormat();
var
  p:DWORD;
begin
  SetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SSHORTDATE,pchar('yyyy-MM-dd')); //设置短日期格式
  SetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SLONGDATE,pchar('yyyy''年''M''月 ''d''日'')); //设置长日期格式为 yyyy'年'M'月'd'日',“年月日”字符必须用单引号括起来。Delphi字符串里必须用两个单引号。
  SetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_STIMEFORMAT,pchar('H:mm:ss')); //设置时间格式,24小时制
  SendMessageTimeOut(HWND_BROADCAST,WM_SETTINGCHANGE,0,0,SMTO_ABORTIFHUNG,10,p);//设置完成后必须调用,通知其他程序格式已经更改,否则即使是程序自身也不能使用新设置的格式
end;

在程序初始化时调用GetDateTimeFormat,将取出的设置保存起来,然后用SetDateTimeFormat设置需要的格式。在程序退出时再次调用SetDateTimeFormat将保存的值写回去。
当然,如果程序已经在运行,别的程序也象我们这样把格式改成它需要的格式,那就没办法了,同时就只能运行一个,否则会互相干扰。如果一定要想办法的话,或许可以处理 WM_SETTINGCHANGE 消息,再把改掉的改回来?有点强盗。

http://tb.blog.csdn.net/TrackBack.aspx?PostId=1342624




解决2:从windows系统里设置。控制面板-->区域选择-->时间-->把时间格式里的"h:mm:ss"改成"H:mm:ss"  ,注意:这样时间格式虽然是24小时制,但是也会出现像
2006-11-1 上午 11:22:22
这样的时间,似乎番茄花园版的windows默认的设置。
要在上述步骤中的对话框里将上下午格式设置为am,pm。番茄花园版的默认设置就是上午和下午,所以其时间是
2006-11-1 上午 11:22:22
,设为am,pm之后才是2006-11-1  11:22:22。




引发的问题:
本文的问题,明白之后就容易解决,但问题在于:程序写好后,在用户机上安装之后出错,很难想到是这个问题。
如何在程序中设置,当出问题时,可以判断问题的大概来源。
当然,捕获异常是一种方式,在java中有比较细致的异常控制,可能问题会好些。
但是在delphi中,编程时很难想到在捕获时间是设置一个异常,如何解决?

再想想,java的异常机制真的很不错,似乎。

但这个优势似乎在调试时还不错,或者在web环境下(出错时也有异常提示),
在桌面环境下,运行一个编译好的程序,出现问题时,该如何捕捉问题来源?
似乎有人提到在程序中设置一些开关通过开关的开和闭,在出现问题时跟踪程序的运行,从而捕捉问题。
问题又是:该方案可行的话,如何设置开关:开关的位置,多少,形式,程序跟踪时的跟踪的项目的选择,,,,,,,,,,,,,,,,,
原创粉丝点击