1. 程式人生 > >java對世界各個時區(TimeZone)的通用轉換處理方法

java對世界各個時區(TimeZone)的通用轉換處理方法

在進行國際性軟體專案開發的過程中,有時候會碰到一些比較特殊的要求。比如:比如說,你做的是個購物網站(假設伺服器放在中國上海),當全世界客戶在你的網站上下訂單買東西后,往往希望看到客戶所在地下單時間,比如說我是個美國紐約人,我在你的網站上下單後,你給我看到一個上海的下單時間,會覺得非常的奇怪。眾所周知,紐約時間相對上海時間大約要晚13小時,如果讓客戶看到本地時區的時間,將變得更加符合客戶的時間觀念,使得客戶理解比較方便。

其實,java中早已考慮過世界時區(TimeZone)這個問題,並給出了比較合理的解決方法,可以比較方便的進行世界時區時間的轉化,將一個時區的時間轉換成另一個時區的時間。可以看看下面的的實際例子(執行例子的main()方法)。

關於如何知道客戶所在的時區,可以根據客戶所在的ip或者使用者註冊提供的國家來計算出所在的時區。

Java程式碼 複製程式碼 收藏程式碼
  1. /*  
  2.  * Created on 2005-6-10  
  3.  * Author stephen  
  4.  * Email zhoujianqiang AT gmail DOT com  
  5.  * CopyRight(C)2005-2008 , All rights reserved.  
  6.  */
  7. package com.soft4j.utility;   
  8. import java.text.ParseException;   
  9. import java.text.SimpleDateFormat;   
  10. import java.util.Date;   
  11. import java.util.GregorianCalendar;   
  12. import java.util.TimeZone;   
  13. import java.util.Vector;   
  14. import com.soft4j.log.Log;   
  15. /**  
  16.  * 與日期、時間相關的一些常用工具方法.  
  17.  * <p>  
  18.  * 日期(時間)的常用格式(formater)主要有: <br>  
  19.  * yyyy-MM-dd HH:mm:ss <br>  
  20.  *   
  21.  * @author stephen  
  22.  * @version 1.0.0  
  23.  */
  24. publicfinalclass DateTool {   
  25. /**
     
  26.      * 對日期(時間)中的日進行加減計算. <br>  
  27.      * 例子: <br>  
  28.      * 如果Date型別的d為 2005年8月20日,那麼 <br>  
  29.      * calculateByDate(d,-10)的值為2005年8月10日 <br>  
  30.      * 而calculateByDate(d,+10)的值為2005年8月30日 <br>  
  31.      *   
  32.      * @param d  
  33.      *            日期(時間).  
  34.      * @param amount  
  35.      *            加減計算的幅度.+n=加n天;-n=減n天.  
  36.      * @return 計算後的日期(時間).  
  37.      */
  38. publicstatic Date calculateByDate(Date d, int amount) {   
  39. return calculate(d, GregorianCalendar.DATE, amount);   
  40.     }   
  41. publicstatic Date calculateByMinute(Date d, int amount) {   
  42. return calculate(d, GregorianCalendar.MINUTE, amount);   
  43.     }   
  44. publicstatic Date calculateByYear(Date d, int amount) {   
  45. return calculate(d, GregorianCalendar.YEAR, amount);   
  46.     }   
  47. /**  
  48.      * 對日期(時間)中由field引數指定的日期成員進行加減計算. <br>  
  49.      * 例子: <br>  
  50.      * 如果Date型別的d為 2005年8月20日,那麼 <br>  
  51.      * calculate(d,GregorianCalendar.YEAR,-10)的值為1995年8月20日 <br>  
  52.      * 而calculate(d,GregorianCalendar.YEAR,+10)的值為2015年8月20日 <br>  
  53.      *   
  54.      * @param d  
  55.      *            日期(時間).  
  56.      * @param field  
  57.      *            日期成員. <br>  
  58.      *            日期成員主要有: <br>  
  59.      *            年:GregorianCalendar.YEAR <br>  
  60.      *            月:GregorianCalendar.MONTH <br>  
  61.      *            日:GregorianCalendar.DATE <br>  
  62.      *            時:GregorianCalendar.HOUR <br>  
  63.      *            分:GregorianCalendar.MINUTE <br>  
  64.      *            秒:GregorianCalendar.SECOND <br>  
  65.      *            毫秒:GregorianCalendar.MILLISECOND <br>  
  66.      * @param amount  
  67.      *            加減計算的幅度.+n=加n個由引數field指定的日期成員值;-n=減n個由引數field代表的日期成員值.  
  68.      * @return 計算後的日期(時間).  
  69.      */
  70. privatestatic Date calculate(Date d, int field, int amount) {   
  71. if (d == null)   
  72. returnnull;   
  73.         GregorianCalendar g = new GregorianCalendar();   
  74.         g.setGregorianChange(d);   
  75.         g.add(field, amount);   
  76. return g.getTime();   
  77.     }   
  78. /**  
  79.      * 日期(時間)轉化為字串.  
  80.      *   
  81.      * @param formater  
  82.      *            日期或時間的格式.  
  83.      * @param aDate  
  84.      *            java.util.Date類的例項.  
  85.      * @return 日期轉化後的字串.  
  86.      */
  87. publicstatic String date2String(String formater, Date aDate) {   
  88. if (formater == null || "".equals(formater))   
  89. returnnull;   
  90. if (aDate == null)   
  91. returnnull;   
  92. return (new SimpleDateFormat(formater)).format(aDate);   
  93.     }   
  94. /**  
  95.      * 當前日期(時間)轉化為字串.  
  96.      *   
  97.      * @param formater  
  98.      *            日期或時間的格式.  
  99.      * @return 日期轉化後的字串.  
  100.      */
  101. publicstatic String date2String(String formater) {   
  102. return date2String(formater, new Date());   
  103.     }   
  104. /**  
  105.      * 獲取當前日期對應的星期數.  
  106.      * <br>1=星期天,2=星期一,3=星期二,4=星期三,5=星期四,6=星期五,7=星期六  
  107.      * @return 當前日期對應的星期數  
  108.      */
  109. publicstaticint dayOfWeek() {   
  110.         GregorianCalendar g = new GregorianCalendar();   
  111. int ret = g.get(java.util.Calendar.DAY_OF_WEEK);   
  112.         g = null;   
  113. return ret;   
  114.     }   
  115. /**  
  116.      * 獲取所有的時區編號. <br>  
  117.      * 排序規則:按照ASCII字元的正序進行排序. <br>  
  118.      * 排序時候忽略字元大小寫.  
  119.      *   
  120.      * @return 所有的時區編號(時區編號已經按照字元[忽略大小寫]排序).  
  121.      */
  122. publicstatic String[] fecthAllTimeZoneIds() {   
  123.         Vector v = new Vector();   
  124.         String[] ids = TimeZone.getAvailableIDs();   
  125. for (int i = 0; i < ids.length; i++) {   
  126.             v.add(ids[i]);   
  127.         }   
  128.         java.util.Collections.sort(v, String.CASE_INSENSITIVE_ORDER);   
  129.         v.copyInto(ids);   
  130.         v = null;   
  131. return ids;   
  132.     }   
  133. /**  
  134.      * 測試的main方法.  
  135.      *   
  136.      * @param argc  
  137.      */
  138. publicstaticvoid main(String[] argc) {   
  139.         String[] ids = fecthAllTimeZoneIds();   
  140.         String nowDateTime =date2String("yyyy-MM-dd HH:mm:ss");   
  141.         System.out.println("The time Asia/Shanhai is " + nowDateTime);//程式本地執行所在時區為[Asia/Shanhai]
  142. //顯示世界每個時區當前的實際時間
  143. for(int i=0;i <ids.length;i++){   
  144.             System.out.println(" * " + ids[i] + "=" + string2TimezoneDefault(nowDateTime,ids[i]));    
  145.         }   
  146. //顯示程式執行所在地的時區
  147.         System.out.println("TimeZone.getDefault().getID()=" +TimeZone.getDefault().getID());   
  148.     }   
  149. /**  
  150.      * 將日期時間字串根據轉換為指定時區的日期時間.  
  151.      *   
  152.      * @param srcFormater  
  153.      *            待轉化的日期時間的格式.  
  154.      * @param srcDateTime  
  155.      *            待轉化的日期時間.  
  156.      * @param dstFormater  
  157.      *            目標的日期時間的格式.  
  158.      * @param dstTimeZoneId  
  159.      *            目標的時區編號.  
  160.      *   
  161.      * @return 轉化後的日期時間.  
  162.      */
  163. publicstatic String string2Timezone(String srcFormater,   
  164.             String srcDateTime, String dstFormater, String dstTimeZoneId) {   
  165. if (srcFormater == null || "".equals(srcFormater))   
  166. returnnull;   
  167. if (srcDateTime == null || "".equals(srcDateTime))   
  168. returnnull;   
  169. if (dstFormater == null || "".equals(dstFormater))   
  170. returnnull;   
  171. if (dstTimeZoneId == null || "".equals(dstTimeZoneId))   
  172. returnnull;   
  173.         SimpleDateFormat sdf = new SimpleDateFormat(srcFormater);   
  174. try {   
  175. int diffTime = getDiffTimeZoneRawOffset(dstTimeZoneId);   
  176.             Date d = sdf.parse(srcDateTime);   
  177. long nowTime = d.getTime();   
  178. long newNowTime = nowTime - diffTime;   
  179.             d = new Date(newNowTime);   
  180. return date2String(dstFormater, d);   
  181.         } catch (ParseException e) {   
  182.             Log.output(e.toString(), Log.STD_ERR);   
  183. returnnull;   
  184.         } finally {   
  185.             sdf = null;   
  186.         }   
  187.     }   
  188. /**  
  189.      * 獲取系統當前預設時區與UTC的時間差.(單位:毫秒)  
  190.      *   
  191.      * @return 系統當前預設時區與UTC的時間差.(單位:毫秒)  
  192.      */
  193. privatestaticint getDefaultTimeZoneRawOffset() {   
  194. return TimeZone.getDefault().getRawOffset();   
  195.     }   
  196. /**  
  197.      * 獲取指定時區與UTC的時間差.(單位:毫秒)  
  198.      *   
  199.      * @param timeZoneId  
  200.      *            時區Id  
  201.      * @return 指定時區與UTC的時間差.(單位:毫秒)  
  202.      */
  203. privatestaticint getTimeZoneRawOffset(String timeZoneId) {   
  204. return TimeZone.getTimeZone(timeZoneId).getRawOffset();   
  205.     }   
  206. /**  
  207.      * 獲取系統當前預設時區與指定時區的時間差.(單位:毫秒)  
  208.      *   
  209.      * @param timeZoneId  
  210.      *            時區Id  
  211.      * @return 系統當前預設時區與指定時區的時間差.(單位:毫秒)  
  212.      */
  213. privatestaticint getDiffTimeZoneRawOffset(String timeZoneId) {   
  214. return TimeZone.getDefault().getRawOffset()   
  215.                 - TimeZone.getTimeZone(timeZoneId).getRawOffset();   
  216.     }   
  217. /**  
  218.      * 將日期時間字串根據轉換為指定時區的日期時間.  
  219.      *   
  220.      * @param srcDateTime  
  221.      *            待轉化的日期時間.  
  222.      * @param dstTimeZoneId  
  223.      *            目標的時區編號.  
  224.      *   
  225.      * @return 轉化後的日期時間.  
  226.      * @see #string2Timezone(String, String, String, String)  
  227.      */
  228. publicstatic String string2TimezoneDefault(String srcDateTime,   
  229.             String dstTimeZoneId) {   
  230. return string2Timezone("yyyy-MM-dd HH:mm:ss", srcDateTime,   
  231. "yyyy-MM-dd HH:mm:ss", dstTimeZoneId);   
  232.     }   
  233. }