一、问题重现

随着企业向国际化方向发现,软件也不到不断向国际化发展。像软件实现多语言方案等等。但是服务端与客户端不在同一时区里,就会导致客户端上时间可能不准确,比如客户端要下载一份服务器上日志,日志上会有时间,就无法提供准备时间,因为用户一般都会以自己所在的时区上时间来看日志,但是日志却以服务端上时区显示时间。

二、问题分析

1、用户需要也是能够使用用户所在时区的时间。

2、服务端写日志一定以服务端上的时区或者以0时区来写入日志。

3、这样就用户下载后日志上的时间就不是以用户的时区为时间的基准了,即时间不准确。

三、解决方案

总方案是客户端在下载前先告诉服务端要以什么时区进入写入日志,然后服务端就以该时区作为基准对日志上的时间做一定修改。

四、代码实现

1、客户端的代码实现

1.1 以C++技术开发的,获取时间区的方式与代码:


[cpp]view plaincopy

TIME_ZONE_INFORMATIONtziOld;

DWORDdwRet;

dwRet=GetTimeZoneInformation(&tziOld);//该方法是C++自带API

if(dwRet==TIME_ZONE_ID_INVALID)

{

LOGT(Log_Error)<<"GetTimezonefaile";

}

floatfTimezone=(-tziOld.Bias)/60;//该"tziOld.Bias"数值是分钟,如果是东八区,这里表示"-480"。</span>

1.2 以Javascript技术开发,获取时区的方式与代码:

[javascript]view plaincopy

varcurDateTime=newDate();

varnTimezone=curDateTime.getTimezoneOffset();

g_fTimezone=(-nTimezone)/60;//同上

网页客户端如果使用“2014-10-10T12:20:20+08:00”这样格式的字符串进入客户端与服务端通信。


1.2.1 服务端若上述格式发送网页客户端,那网页客户端要将其转换成客户端所在时区的时间。像火狐等浏览器可以直接通过Date类转换,但是IE浏览器却无法直接转换。那就必须使用其他方案将其转换。(考虑浏览器的兼容性,这里使用下面的方法)其Javascript代码如下:


[javascript]view plaincopy

varnSplitTime=strDate.indexOf("T");//注:这里的strDate就是上述格式的时间串“2014-10-10T12:20:20+08:00”

varbEastTimezone=true;

varnSplitZone=strDate.indexOf("+");//这里看一下是东区还是西区的

if(nSplitZone==-1){

bEastTimezone=false;

nSplitZone=strDate.indexOf("-");

}

varstrDateTemp=strDate.slice(0,nSplitTime);

varstrTimeTemp=strDate.slice(nSplitTime+1,nSplitZone);

varstrTimeZoneTemp=strDate.slice(nSplitZone+1);

vararrayDate=strDateTemp.split("-");

vararrayTime=strTimeTemp.split(":");

vararrayZone=strTimeZoneTemp.split(":");

varnTimeZoneOffset=parseInt(arrayZone[0],10)*60+parseInt(arrayZone[1],10);

if(!bEastTimezone){

nTimeZone=-nTimeZone;

}

vardateNewTime=newDate(parseInt(arrayDate[0],10),parseInt(arrayDate[1],10)-1,

parseInt(arrayDate[2],10),parseInt(arrayTime[0],10),

parseInt(arrayTime[1],10),parseInt(arrayTime[2],10));

varnTimezoneDiff=(-dateNewTime.getTimezoneOffset())-nTimeZoneOffset;//算出服务端与客户端的时区差

dateNewTime=dateNewTime.setTime(dateNewTime.getTime()+(nTimezoneDiff*60*1000));

varreDate=newDate(dateNewTime);//“reDate"表示最终在客户端展示的时间

1.2.2 客户端要以此格式的时间向服务端发送,这里就对时区显示“+08:00”的格式做一定解析。Javascript代码如下:



[javascript]view plaincopy

varcurDateTime=newDate();

varnTimezone=curDateTime.getTimezoneOffset();

varnDiffMinute=nTimezone%60;

varnDiffHour=(nTimezone-nDiffMinute)/60;

nDiffMinute=Math.abs(nDiffMinute);

nDiffHour=Math.abs(nDiffHour);

if(nTimezone<0){

if(nDiffHour>=10){

g_strTimezone="+"+nDiffHour;

}else{

g_strTimezone="+0"+nDiffHour;

}

}else{

if(nDiffHour>=10){

g_strTimezone="-"+nDiffHour;

}else{

g_strTimezone="-0"+nDiffHour;

}

}

[javascript]view plaincopy

if(nDiffMinute>=10){

g_strTimezone=g_strTimezone+":"+nDiffMinute;

}else{

g_strTimezone=g_strTimezone+":0"+nDiffMinute;

}

2、服务端实现


2.1 服务端如果使用python技术实现,这里主要是客户端下载服务端的日志文件的解析。从上述方案上可以知道,这里需要客户端将它所在时区上传到服务端,服务端才将日志中的时间修改成该时区的时间。python代码实现如下:


[python]view plaincopy

tm=datetime.utcfromtimestamp(tmpTime)//注:tmpTime表示日志中所记录的时间差

tm=tm+timedelta(hours=fTimeZone) //注:fTimeZone就是客户端传过来的时区信息比如“东八区”—>“+8.0","西九点五区"——>"-9.5"。

服务端暂时先考虑这个,其他后续再补。