一、問題重現
隨着企業向國際化方向發現,軟件也不到不斷向國際化發展。像軟件實現多語言方案等等。但是服務端與客戶端不在同一時區裏,就會導致客戶端上時間可能不準確,比如客戶端要下載一份服務器上日誌,日誌上會有時間,就無法提供準備時間,因爲用戶一般都會以自己所在的時區上時間來看日誌,但是日誌卻以服務端上時區顯示時間。
二、問題分析
1、用戶需要也是能夠使用用戶所在時區的時間。
2、服務端寫日誌一定以服務端上的時區或者以0時區來寫入日誌。
3、這樣就用戶下載後日志上的時間就不是以用戶的時區爲時間的基準了,即時間不準確。
三、解決方案
總方案是客戶端在下載前先告訴服務端要以什麼時區進入寫入日誌,然後服務端就以該時區作爲基準對日誌上的時間做一定修改。
四、代碼實現
1、客戶端的代碼實現
1.1 以C++技術開發的,獲取時間區的方式與代碼:
TIME_ZONE_INFORMATION tziOld;
DWORD dwRet;
dwRet = GetTimeZoneInformation(&tziOld); //該方法是C++自帶API
if (dwRet == TIME_ZONE_ID_INVALID)
{
LOGT( Log_Error ) << "Get Timezone faile";
}
float fTimezone = (-tziOld.Bias) / 60;//該"tziOld.Bias"數值是分鐘,如果是東八區,這裏表示"-480"。
1.2 以Javascript技術開發,獲取時區的方式與代碼:var curDateTime = new Date();
var nTimezone = curDateTime.getTimezoneOffset();
g_fTimezone = (-nTimezone) / 60; //同上
網頁客戶端如果使用“2014-10-10T12:20:20+08:00”這樣格式的字符串進入客戶端與服務端通信。
1.2.1 服務端若上述格式發送網頁客戶端,那網頁客戶端要將其轉換成客戶端所在時區的時間。像火狐等瀏覽器可以直接通過Date類轉換,但是IE瀏覽器卻無法直接轉換。那就必須使用其他方案將其轉換。(考慮瀏覽器的兼容性,這裏使用下面的方法)其Javascript代碼如下:
var nSplitTime = strDate.indexOf("T"); //注: 這裏的strDate就是上述格式的時間串 “2014-10-10T12:20:20+08:00”
var bEastTimezone = true;
var nSplitZone = strDate.indexOf("+");//這裏看一下是東區還是西區的
if(nSplitZone == -1){
bEastTimezone = false;
nSplitZone = strDate.indexOf("-");
}
var strDateTemp = strDate.slice(0, nSplitTime);
var strTimeTemp = strDate.slice(nSplitTime + 1, nSplitZone);
var strTimeZoneTemp = strDate.slice(nSplitZone + 1);
var arrayDate = strDateTemp.split("-");
var arrayTime = strTimeTemp.split(":");
var arrayZone = strTimeZoneTemp.split(":");
var nTimeZoneOffset = parseInt(arrayZone[0],10)*60 + parseInt(arrayZone[1],10);
if(!bEastTimezone){
nTimeZone = -nTimeZone;
}
var dateNewTime = new Date(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));
var nTimezoneDiff = (-dateNewTime.getTimezoneOffset()) - nTimeZoneOffset;//算出服務端與客戶端的時區差
dateNewTime = dateNewTime.setTime(dateNewTime.getTime() + (nTimezoneDiff * 60 * 1000));
var reDate = new Date(dateNewTime);//"reDate"表示最終在客戶端展示的時間
1.2.2 客戶端要以此格式的時間向服務端發送,這裏就對時區顯示“+08:00”的格式做一定解析。Javascript代碼如下:
var curDateTime = new Date();
var nTimezone = curDateTime.getTimezoneOffset();
var nDiffMinute = nTimezone % 60;
var nDiffHour = (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;
}
}
if(nDiffMinute >= 10){
g_strTimezone = g_strTimezone + ":" + nDiffMinute;
}else{
g_strTimezone = g_strTimezone + ":0" + nDiffMinute;
}
2、服務端實現
2.1 服務端如果使用python技術實現,這裏主要是客戶端下載服務端的日誌文件的解析。從上述方案上可以知道,這裏需要客戶端將它所在時區上傳到服務端,服務端纔將日誌中的時間修改成該時區的時間。python代碼實現如下:
tm = datetime.utcfromtimestamp(tmpTime) //注:tmpTime 表示日誌中所記錄的時間差
tm = tm + timedelta(hours=fTimeZone) //注:fTimeZone 就是客戶端傳過來的時區信息 比如“東八區”—>“+8.0" ,"西九點五區"——>"-9.5"。
服務端暫時先考慮這個,其他後續再補。