java國際化之時區問題處理

原文:https://moon-walker.iteye.com/blog/2396035前端

 

在國際化的項目中須要處理的日期時間問題主要有兩點:java

一、日期時間的國際化格式問題處理;spring

二、日期時間的時區問題處理,這兩個問題要區分開,不要弄混了。數據庫

 

日期時間國際化化格式處理後端

 

對應的關鍵詞:Locale瀏覽器

日期時間的國際化格式指的是在不一樣的國家和地區對日期時間的顯示方式不一樣,主要經過不一樣國家地區不一樣的語言習慣,對同一個實現的呈現方式不一樣。在java中須要結合Locale類進行處理:bash

Java代碼  
public static void main(String[] args) {  
        Date date = new Date();  
        Locale locale = Locale.CHINA;  
        DateFormat shortDf = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, locale);  
        System.out.println("中國格式:"+shortDf.format(date));  
   
        locale = Locale.ENGLISH;  
        shortDf = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, locale);  
        System.out.println("英國格式:"+shortDf.format(date));  
}  

 

 執行mian方法,結果爲:服務器

 
  1. 中國格式:2017-10-12 10:29:44  
  2. 英國格式:Oct 12, 2017 10:29:44 AM  

 

在Spring MVC項目中,通常能夠藉助spring自動的國際化解決方案,在視圖層對不一樣的國家使用不一樣的locale參數進行處理。jvm

 

日期時間國際化化時區處理ide

對應的關鍵詞:TimeZone

日期時間的時區問題,指的是在同一時刻,地球上的各個地區的日期時間不一樣。全球劃分爲24個時區,每一個相鄰時區時間相差一個小時(中國爲了方便統一,雖然跨越5個時區,但都使用同一個時區時間),也就是說在同一時刻,全球同一時刻對應的當地時間的小時數有多是0-23點之間的一個值。這裏拿中國上海和英國倫敦舉例:

Java代碼  
public static void main(String[] args) {  
        Date date = new Date();  
        Locale locale = Locale.CHINA;  
        DateFormat shortDf = DateFormat.getDateTimeInstance(DateFormat.FULL,DateFormat.FULL, locale);  
        shortDf.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai"));//Asia/Chongqing  
        System.out.println(TimeZone.getDefault().getID());  
        System.out.println("中國當前日期時間:" + shortDf.format(date));  
   
        locale = Locale.ENGLISH;  
        shortDf = DateFormat.getDateTimeInstance(DateFormat.MEDIUM,DateFormat.MEDIUM, locale);  
        shortDf.setTimeZone(TimeZone.getTimeZone("Europe/London"));  
        System.out.println("英國當前日期時間:"+shortDf.format(date));  
    }

執行main方法,運行結果爲:

  1. 中國當前日期時間:2017-10-12 10:55:55  
  2. 英國當前日期時間:Oct 12, 2017 3:55:55 AM  

說明同一時刻,中國上海和英國倫敦相差7個小時,也就是相差7個時區。

 

時區對國際化項目帶來的問題

 

日期時間的國際化格式處理 只是顯示風格問題 相對來講比較簡單,但日期時間的國際化時區問題 確比較麻煩,若是處理不當會引發一些兼容性問題。

 

拿最近作的一個泰國項目舉例,咱們一個活動頁建立項目部署在泰國。若是在中國建立一個活動頁,經過時間控件選擇活動的開始時間,這時獲取的時間是從瀏覽器獲取 爲中國時區時間。須要把這個時間傳到後端服務器,存儲到數據庫,但服務器的時間爲泰國時區的時間。中國是東八區 泰國是東七區,相差一個小時。這時有兩種處理辦法:

一、前端傳給後端的是字符串,好比開始時間爲「2017-10-12 08:00:00」, 後端直接使用這個字符串轉換爲泰國的Date 存入數據庫便可。

Java代碼  
public static void main(String[] args) throws Exception{  
        String t="2017-10-12 08:00:00";  
        DateFormat format =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        Date date = format.parse(t);  
        System.out.println(date);  
    }  

看起來比較簡單,但關鍵是這個字符串,前面說了 不一樣的語言國家這個字符的格式不一樣,後端須要根據不一樣的格式進行Format操做。假設換成在英國建立活動,這個Format又得改爲英國的格式。

 

二、前端傳給後端的是時間戳,好比開始時間爲「2017-10-12 08:00:00」,對應的中國的時間戳爲:1507766400000,轉換成泰國的時間就變成:「2017-10-12 07:00:00」,模擬代碼以下:

 

Java代碼  
public static void main(String[] args) throws Exception{  
        String t="2017-10-12 08:00:00";//頁面傳入的時間  
        DateFormat format =  new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");  
        Date date = format.parse(t);  
        System.out.println("中國:"+t);  
   
   
        long tl = date.getTime();//模擬前端轉換爲中國的時間戳  
        TimeZone timeZone2 = TimeZone.getTimeZone("Asia/Bangkok");  
        format.setTimeZone(timeZone2);  
        String d2 = format.format(tl);  
        System.out.println("泰國:"+d2);//存入數據庫的時間  
}  

執行結果爲:

  1. 中國:2017-10-12 08:00:00  
  2. 泰國:2017-10-12 07:00:00 

說明直接傳給後端時間搓有問題,但有解決辦法:首前後端封裝一個接口後獲取服務器相對GMT(格林尼治標準時間)時間的偏移量:

Java代碼  
TimeZone zone = TimeZone.getDefault();  
System.out.println(zone.getRawOffset());  

這段代碼放在不一樣時區的服務器上執行結果會不一樣(前提是服務器的時區設置跟本地時區一致)。若是在泰國執行結果爲25200000ms,換算成小時爲7,說明泰國的時區的偏移量相對於GMT標準時間相差7小時。下文簡稱「時區偏移量」。

 

如下操做都在瀏覽器中經過js代碼實現:

前端首先調用該接口獲取服務器的時區偏移量,再在瀏覽器上獲取本地的時區偏移量,計算出兩個偏移量的差值。本地瀏覽器上獲取當前的時間戳,減去上一步計算出來的差值便可獲得服務器這個時間的時間戳,把這個時間戳傳給後端 再轉換成時間,就是服務器對應的時間,存入數據庫便可。

Js代碼  
//服務的時區偏移量,經過接口得到,注意換成負值  
var serveroffset=-25200000;  
var d = new Date();  
//獲取本地瀏覽器的時區偏移量  
var localOffset = d.getTimezoneOffset() * 60000;  
//的到本地和偏移量的差值  
var deffoffset=localOffset-(serveroffset);  
//獲取本地瀏覽器時間戳  
var localTime = d.getTime();  
//計算出傳到服務器的時間戳  
var servertime=localTime+deffoffset;  

經過上述方式,能夠實現服務器全球各地部署,系統均可以正常使用。

 

Java中的TimeZone類

 

Java中處理時區使用的是TimeZone類,經過TimeZone.getTimeZone(String id)方法能夠獲取到指定時區的TimeZone實例,經過TimeZone實例能夠獲取到相對於GMT標準時間的偏移量。該方法的參數ID能夠是GMT、 UTC、CST等時區,也能夠是城市名:

 

Java代碼  
public static void main(String[] args) throws Exception{  
   
        TimeZone timeZone1 = TimeZone.getDefault();//獲取當前服務器時區  
        TimeZone timeZone2 = TimeZone.getTimeZone("Asia/Shanghai");//獲取上海時區  
        TimeZone timeZone3 = TimeZone.getTimeZone("GMT");//獲取格林威治標準時區  
        TimeZone timeZone4 = TimeZone.getTimeZone("GMT+8");//獲取東八區時區  
        TimeZone timeZone5 = TimeZone.getTimeZone("UTC");//獲取UTC標準時間  
        TimeZone timeZone6 = TimeZone.getTimeZone("CST");//獲取CST時區  
   
        System.out.println(timeZone1.getRawOffset());  
        System.out.println(timeZone2.getRawOffset());  
        System.out.println(timeZone3.getRawOffset());  
        System.out.println(timeZone4.getRawOffset());  
        System.out.println(timeZone5.getRawOffset());  
        System.out.println(timeZone6.getRawOffset());  
    }  

 運行結果:

  1. 28800000  
  2. 28800000  
  3. 0  
  4. 28800000  
  5. 0  
  6. -21600000 

GMT和 UTC能夠視爲幾乎是等同的,UTC更精準,有閏秒的概念。

其中TimeZone.getTimeZone("Asia/Shanghai")和TimeZone.getTimeZone("GMT+8")是相同的,能夠相互替換使用。又好比泰國的時區ID使用"Asia/Bangkok"和"GMT+7"是相同。

 

經過閱讀jdk源碼能夠發現,TimeZone ID是在java裏ZoneInfoFile類加載的。在jvm初始化的時候,會讀取jdk安裝目錄下的 ${ java.home } /jre/lib/tzdb.dat,放到其成員變量爲zones的ConcurrentHashMap裏。當調用TimeZone.getTimeZone(id)方法時,會用id到這個map裏進行匹配獲取到指定id的時區。

 

最後附上TimeZone 的ID列表,要獲取對應城市的時區,須要先查詢到其對應的ID,對應的其實就是 ${ java.home } /jre/lib/tzdb.dat文件中的內容。

 
Etc/GMT+12  
Etc/GMT+11  
MIT  
Pacific/Apia  
Pacific/Midway  
Pacific/Niue  
Pacific/Pago_Pago  
Pacific/Samoa  
US/Samoa  
America/Adak  
America/Atka  
Etc/GMT+10  
HST  
Pacific/Fakaofo  
Pacific/Honolulu  
Pacific/Johnston  
Pacific/Rarotonga  
Pacific/Tahiti  
SystemV/HST10  
US/Aleutian  
US/Hawaii  
Pacific/Marquesas  
AST  
America/Anchorage  
America/Juneau  
America/Nome  
America/Yakutat  
Etc/GMT+9  
Pacific/Gambier  
SystemV/YST9  
SystemV/YST9YDT  
US/Alaska  
America/Dawson  
America/Ensenada  
America/Los_Angeles  
America/Tijuana  
America/Vancouver  
America/Whitehorse  
Canada/Pacific  
Canada/Yukon  
Etc/GMT+8  
Mexico/BajaNorte  
PST  
PST8PDT  
Pacific/Pitcairn  
SystemV/PST8  
SystemV/PST8PDT  
US/Pacific  
US/Pacific-New  
America/Boise  
America/Cambridge_Bay  
America/Chihuahua  
America/Dawson_Creek  
America/Denver  
America/Edmonton  
America/Hermosillo  
America/Inuvik  
America/Mazatlan  
America/Phoenix  
America/Shiprock  
America/Yellowknife  
Canada/Mountain  
Etc/GMT+7  
MST  
MST7MDT  
Mexico/BajaSur  
Navajo  
PNT  
SystemV/MST7  
SystemV/MST7MDT  
US/Arizona  
US/Mountain  
America/Belize  
America/Cancun  
America/Chicago  
America/Costa_Rica  
America/El_Salvador  
America/Guatemala  
America/Indiana/Knox  
America/Indiana/Tell_City  
America/Knox_IN  
America/Managua  
America/Menominee  
America/Merida  
America/Mexico_City  
America/Monterrey  
America/North_Dakota/Center  
America/North_Dakota/New_Salem  
America/Rainy_River  
America/Rankin_Inlet  
America/Regina  
America/Swift_Current  
America/Tegucigalpa  
America/Winnipeg  
CST  
CST6CDT  
Canada/Central  
Canada/East-Saskatchewan  
Canada/Saskatchewan  
Chile/EasterIsland  
Etc/GMT+6  
Mexico/General  
Pacific/Easter  
Pacific/Galapagos  
SystemV/CST6  
SystemV/CST6CDT  
US/Central  
US/Indiana-Starke  
America/Atikokan  
America/Bogota  
America/Cayman  
America/Coral_Harbour  
America/Detroit  
America/Fort_Wayne  
America/Grand_Turk  
America/Guayaquil  
America/Havana  
America/Indiana/Indianapolis  
America/Indiana/Marengo  
America/Indiana/Petersburg  
America/Indiana/Vevay  
America/Indiana/Vincennes  
America/Indiana/Winamac  
America/Indianapolis  
America/Iqaluit  
America/Jamaica  
America/Kentucky/Louisville  
America/Kentucky/Monticello  
America/Lima  
America/Louisville  
America/Montreal  
America/Nassau  
America/New_York  
America/Nipigon  
America/Panama  
America/Pangnirtung  
America/Port-au-Prince  
America/Resolute  
America/Thunder_Bay  
America/Toronto  
Canada/Eastern  
Cuba  
EST  
EST5EDT  
Etc/GMT+5  
IET  
Jamaica  
SystemV/EST5  
SystemV/EST5EDT  
US/East-Indiana  
US/Eastern  
US/Michigan  
America/Caracas  
America/Anguilla  
America/Antigua  
America/Aruba  
America/Asuncion  
America/Barbados  
America/Blanc-Sablon  
America/Boa_Vista  
America/Campo_Grande  
America/Cuiaba  
America/Curacao  
America/Dominica  
America/Eirunepe  
America/Glace_Bay  
America/Goose_Bay  
America/Grenada  
America/Guadeloupe  
America/Guyana  
America/Halifax  
America/La_Paz  
America/Manaus  
America/Marigot  
America/Martinique  
America/Moncton  
America/Montserrat  
America/Port_of_Spain  
America/Porto_Acre  
America/Porto_Velho  
America/Puerto_Rico  
America/Rio_Branco  
America/Santiago  
America/Santo_Domingo  
America/St_Barthelemy  
America/St_Kitts  
America/St_Lucia  
America/St_Thomas  
America/St_Vincent  
America/Thule  
America/Tortola  
America/Virgin  
Antarctica/Palmer  
Atlantic/Bermuda  
Atlantic/Stanley  
Brazil/Acre  
Brazil/West  
Canada/Atlantic  
Chile/Continental  
Etc/GMT+4  
PRT  
SystemV/AST4  
SystemV/AST4ADT  
America/St_Johns  
CNT  
Canada/Newfoundland  
AGT  
America/Araguaina  
America/Argentina/Buenos_Aires  
America/Argentina/Catamarca  
America/Argentina/ComodRivadavia  
America/Argentina/Cordoba  
America/Argentina/Jujuy  
America/Argentina/La_Rioja  
America/Argentina/Mendoza  
America/Argentina/Rio_Gallegos  
America/Argentina/Salta  
America/Argentina/San_Juan  
America/Argentina/San_Luis  
America/Argentina/Tucuman  
America/Argentina/Ushuaia  
America/Bahia  
America/Belem  
America/Buenos_Aires  
America/Catamarca  
America/Cayenne  
America/Cordoba  
America/Fortaleza  
America/Godthab  
America/Jujuy  
America/Maceio  
America/Mendoza  
America/Miquelon  
America/Montevideo  
America/Paramaribo  
America/Recife  
America/Rosario  
America/Santarem  
America/Sao_Paulo  
Antarctica/Rothera  
BET  
Brazil/East  
Etc/GMT+3  
America/Noronha  
Atlantic/South_Georgia  
Brazil/DeNoronha  
Etc/GMT+2  
America/Scoresbysund  
Atlantic/Azores  
Atlantic/Cape_Verde  
Etc/GMT+1  
Africa/Abidjan  
Africa/Accra  
Africa/Bamako  
Africa/Banjul  
Africa/Bissau  
Africa/Casablanca  
Africa/Conakry  
Africa/Dakar  
Africa/El_Aaiun  
Africa/Freetown  
Africa/Lome  
Africa/Monrovia  
Africa/Nouakchott  
Africa/Ouagadougou  
Africa/Sao_Tome  
Africa/Timbuktu  
America/Danmarkshavn  
Atlantic/Canary  
Atlantic/Faeroe  
Atlantic/Faroe  
Atlantic/Madeira  
Atlantic/Reykjavik  
Atlantic/St_Helena  
Eire  
Etc/GMT  
Etc/GMT+0  
Etc/GMT-0  
Etc/GMT0  
Etc/Greenwich  
Etc/UCT  
Etc/UTC  
Etc/Universal  
Etc/Zulu  
Europe/Belfast  
Europe/Dublin  
Europe/Guernsey  
Europe/Isle_of_Man  
Europe/Jersey  
Europe/Lisbon  
Europe/London  
GB  
GB-Eire  
GMT  
GMT0  
Greenwich  
Iceland  
Portugal  
UCT  
UTC  
Universal  
WET  
Zulu  
Africa/Algiers  
Africa/Bangui  
Africa/Brazzaville  
Africa/Ceuta  
Africa/Douala  
Africa/Kinshasa  
Africa/Lagos  
Africa/Libreville  
Africa/Luanda  
Africa/Malabo  
Africa/Ndjamena  
Africa/Niamey  
Africa/Porto-Novo  
Africa/Tunis  
Africa/Windhoek  
Arctic/Longyearbyen  
Atlantic/Jan_Mayen  
CET  
ECT  
Etc/GMT-1  
Europe/Amsterdam  
Europe/Andorra  
Europe/Belgrade  
Europe/Berlin  
Europe/Bratislava  
Europe/Brussels  
Europe/Budapest  
Europe/Copenhagen  
Europe/Gibraltar  
Europe/Ljubljana  
Europe/Luxembourg  
Europe/Madrid  
Europe/Malta  
Europe/Monaco  
Europe/Oslo  
Europe/Paris  
Europe/Podgorica  
Europe/Prague  
Europe/Rome  
Europe/San_Marino  
Europe/Sarajevo  
Europe/Skopje  
Europe/Stockholm  
Europe/Tirane  
Europe/Vaduz  
Europe/Vatican  
Europe/Vienna  
Europe/Warsaw  
Europe/Zagreb  
Europe/Zurich  
MET  
Poland  
ART  
Africa/Blantyre  
Africa/Bujumbura  
Africa/Cairo  
Africa/Gaborone  
Africa/Harare  
Africa/Johannesburg  
Africa/Kigali  
Africa/Lubumbashi  
Africa/Lusaka  
Africa/Maputo  
Africa/Maseru  
Africa/Mbabane  
Africa/Tripoli  
Asia/Amman  
Asia/Beirut  
Asia/Damascus  
Asia/Gaza  
Asia/Istanbul  
Asia/Jerusalem  
Asia/Nicosia  
Asia/Tel_Aviv  
CAT  
EET  
Egypt  
Etc/GMT-2  
Europe/Athens  
Europe/Bucharest  
Europe/Chisinau  
Europe/Helsinki  
Europe/Istanbul  
Europe/Kaliningrad  
Europe/Kiev  
Europe/Mariehamn  
Europe/Minsk  
Europe/Nicosia  
Europe/Riga  
Europe/Simferopol  
Europe/Sofia  
Europe/Tallinn  
Europe/Tiraspol  
Europe/Uzhgorod  
Europe/Vilnius  
Europe/Zaporozhye  
Israel  
Libya  
Turkey  
Africa/Addis_Ababa  
Africa/Asmara  
Africa/Asmera  
Africa/Dar_es_Salaam  
Africa/Djibouti  
Africa/Kampala  
Africa/Khartoum  
Africa/Mogadishu  
Africa/Nairobi  
Antarctica/Syowa  
Asia/Aden  
Asia/Baghdad  
Asia/Bahrain  
Asia/Kuwait  
Asia/Qatar  
Asia/Riyadh  
EAT  
Etc/GMT-3  
Europe/Moscow  
Europe/Volgograd  
Indian/Antananarivo  
Indian/Comoro  
Indian/Mayotte  
W-SU  
Asia/Riyadh87  
Asia/Riyadh88  
Asia/Riyadh89  
Mideast/Riyadh87  
Mideast/Riyadh88  
Mideast/Riyadh89  
Asia/Tehran  
Iran  
Asia/Baku  
Asia/Dubai  
Asia/Muscat  
Asia/Tbilisi  
Asia/Yerevan  
Etc/GMT-4  
Europe/Samara  
Indian/Mahe  
Indian/Mauritius  
Indian/Reunion  
NET  
Asia/Kabul  
Asia/Aqtau  
Asia/Aqtobe  
Asia/Ashgabat  
Asia/Ashkhabad  
Asia/Dushanbe  
Asia/Karachi  
Asia/Oral  
Asia/Samarkand  
Asia/Tashkent  
Asia/Yekaterinburg  
Etc/GMT-5  
Indian/Kerguelen  
Indian/Maldives  
PLT  
Asia/Calcutta  
Asia/Colombo  
Asia/Kolkata  
IST  
Asia/Kathmandu  
Asia/Katmandu  
Antarctica/Mawson  
Antarctica/Vostok  
Asia/Almaty  
Asia/Bishkek  
Asia/Dacca  
Asia/Dhaka  
Asia/Novosibirsk  
Asia/Omsk  
Asia/Qyzylorda  
Asia/Thimbu  
Asia/Thimphu  
BST  
Etc/GMT-6  
Indian/Chagos  
Asia/Rangoon  
Indian/Cocos  
Antarctica/Davis  
Asia/Bangkok  
Asia/Ho_Chi_Minh  
Asia/Hovd  
Asia/Jakarta  
Asia/Krasnoyarsk  
Asia/Phnom_Penh  
Asia/Pontianak  
Asia/Saigon  
Asia/Vientiane  
Etc/GMT-7  
Indian/Christmas  
VST  
Antarctica/Casey  
Asia/Brunei  
Asia/Choibalsan  
Asia/Chongqing  
Asia/Chungking  
Asia/Harbin  
Asia/Hong_Kong  
Asia/Irkutsk  
Asia/Kashgar  
Asia/Kuala_Lumpur  
Asia/Kuching  
Asia/Macao  
Asia/Macau  
Asia/Makassar  
Asia/Manila  
Asia/Shanghai  
Asia/Singapore  
Asia/Taipei  
Asia/Ujung_Pandang  
Asia/Ulaanbaatar  
Asia/Ulan_Bator  
Asia/Urumqi  
Australia/Perth  
Australia/West  
CTT  
Etc/GMT-8  
Hongkong  
PRC  
Singapore  
Australia/Eucla  
Asia/Dili  
Asia/Jayapura  
Asia/Pyongyang  
Asia/Seoul  
Asia/Tokyo  
Asia/Yakutsk  
Etc/GMT-9  
JST  
Japan  
Pacific/Palau  
ROK  
ACT  
Australia/Adelaide  
Australia/Broken_Hill  
Australia/Darwin  
Australia/North  
Australia/South  
Australia/Yancowinna  
AET  
Antarctica/DumontDUrville  
Asia/Sakhalin  
Asia/Vladivostok  
Australia/ACT  
Australia/Brisbane  
Australia/Canberra  
Australia/Currie  
Australia/Hobart  
Australia/Lindeman  
Australia/Melbourne  
Australia/NSW  
Australia/Queensland  
Australia/Sydney  
Australia/Tasmania  
Australia/Victoria  
Etc/GMT-10  
Pacific/Guam  
Pacific/Port_Moresby  
Pacific/Saipan  
Pacific/Truk  
Pacific/Yap  
Australia/LHI  
Australia/Lord_Howe  
Asia/Magadan  
Etc/GMT-11  
Pacific/Efate  
Pacific/Guadalcanal  
Pacific/Kosrae  
Pacific/Noumea  
Pacific/Ponape  
SST  
Pacific/Norfolk  
Antarctica/McMurdo  
Antarctica/South_Pole  
Asia/Anadyr  
Asia/Kamchatka  
Etc/GMT-12  
Kwajalein  
NST  
NZ  
Pacific/Auckland  
Pacific/Fiji  
Pacific/Funafuti  
Pacific/Kwajalein  
Pacific/Majuro  
Pacific/Nauru  
Pacific/Tarawa  
Pacific/Wake  
Pacific/Wallis  
NZ-CHAT  
Pacific/Chatham  
Etc/GMT-13  
Pacific/Enderbury  
Pacific/Tongatapu  
Etc/GMT-14  
Pacific/Kiritimati  
相關文章
相關標籤/搜索