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

在進行國際性軟件項目開發的過程當中,有時候會碰到一些比較特殊的要求。好比:好比說,你作的是個購物網站(假設服務器放在中國上海),當全世界客戶在你的網站上下訂單買東西后,每每但願看到客戶所在地下單時間,好比說我是個美國紐約人,我在你的網站上下單後,你給我看到一個上海的下單時間,會以爲很是的奇怪。衆所周知,紐約時間相對上海時間大約要晚13小時,若是讓客戶看到本地時區的時間,將變得更加符合客戶的時間觀念,使得客戶理解比較方便。 

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

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

/*
 * Created on 2005-6-10
 * Author stephen
 * Email zhoujianqiang AT gmail DOT com
 * CopyRight(C)2005-2008 , All rights reserved.
 */
package com.soft4j.utility;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Vector;

import com.soft4j.log.Log;

/**
 * 與日期、時間相關的一些經常使用工具方法.
 * <p>
 * 日期(時間)的經常使用格式(formater)主要有: <br>
 * yyyy-MM-dd HH:mm:ss <br>
 * 
 * @author stephen
 * @version 1.0.0
 */
public final class DateTool {

    /**
     * 對日期(時間)中的日進行加減計算. <br>
     * 例子: <br>
     * 若是Date類型的d爲 2005年8月20日,那麼 <br>
     * calculateByDate(d,-10)的值爲2005年8月10日 <br>
     * 而calculateByDate(d,+10)的值爲2005年8月30日 <br>
     * 
     * @param d
     *            日期(時間).
     * @param amount
     *            加減計算的幅度.+n=加n天;-n=減n天.
     * @return 計算後的日期(時間).
     */
    public static Date calculateByDate(Date d, int amount) {
        return calculate(d, GregorianCalendar.DATE, amount);
    }
    
    public static Date calculateByMinute(Date d, int amount) {
        return calculate(d, GregorianCalendar.MINUTE, amount);
    }
    
    public static Date calculateByYear(Date d, int amount) {
        return calculate(d, GregorianCalendar.YEAR, amount);
    }

    /**
     * 對日期(時間)中由field參數指定的日期成員進行加減計算. <br>
     * 例子: <br>
     * 若是Date類型的d爲 2005年8月20日,那麼 <br>
     * calculate(d,GregorianCalendar.YEAR,-10)的值爲1995年8月20日 <br>
     * 而calculate(d,GregorianCalendar.YEAR,+10)的值爲2015年8月20日 <br>
     * 
     * @param d
     *            日期(時間).
     * @param field
     *            日期成員. <br>
     *            日期成員主要有: <br>
     *            年:GregorianCalendar.YEAR <br>
     *            月:GregorianCalendar.MONTH <br>
     *            日:GregorianCalendar.DATE <br>
     *            時:GregorianCalendar.HOUR <br>
     *            分:GregorianCalendar.MINUTE <br>
     *            秒:GregorianCalendar.SECOND <br>
     *            毫秒:GregorianCalendar.MILLISECOND <br>
     * @param amount
     *            加減計算的幅度.+n=加n個由參數field指定的日期成員值;-n=減n個由參數field表明的日期成員值.
     * @return 計算後的日期(時間).
     */
    private static Date calculate(Date d, int field, int amount) {
        if (d == null)
            return null;
        GregorianCalendar g = new GregorianCalendar();
        g.setGregorianChange(d);
        g.add(field, amount);
        return g.getTime();
    }

    /**
     * 日期(時間)轉化爲字符串.
     * 
     * @param formater
     *            日期或時間的格式.
     * @param aDate
     *            java.util.Date類的實例.
     * @return 日期轉化後的字符串.
     */
    public static String date2String(String formater, Date aDate) {
        if (formater == null || "".equals(formater))
            return null;
        if (aDate == null)
            return null;
        return (new SimpleDateFormat(formater)).format(aDate);
    }

    /**
     * 當前日期(時間)轉化爲字符串.
     * 
     * @param formater
     *            日期或時間的格式.
     * @return 日期轉化後的字符串.
     */
    public static String date2String(String formater) {
        return date2String(formater, new Date());
    }
    
    /**
     * 獲取當前日期對應的星期數.
     * <br>1=星期天,2=星期一,3=星期二,4=星期三,5=星期四,6=星期五,7=星期六
     * @return 當前日期對應的星期數
     */
    public static int dayOfWeek() {
        GregorianCalendar g = new GregorianCalendar();
        int ret = g.get(java.util.Calendar.DAY_OF_WEEK);
        g = null;
        return ret;
    }


    /**
     * 獲取全部的時區編號. <br>
     * 排序規則:按照ASCII字符的正序進行排序. <br>
     * 排序時候忽略字符大小寫.
     * 
     * @return 全部的時區編號(時區編號已經按照字符[忽略大小寫]排序).
     */
    public static String[] fecthAllTimeZoneIds() {
        Vector v = new Vector();
        String[] ids = TimeZone.getAvailableIDs();
        for (int i = 0; i < ids.length; i++) {
            v.add(ids[i]);
        }
        java.util.Collections.sort(v, String.CASE_INSENSITIVE_ORDER);
        v.copyInto(ids);
        v = null;
        return ids;
    }

    /**
     * 測試的main方法.
     * 
     * @param argc
     */
    public static void main(String[] argc) {
        
        String[] ids = fecthAllTimeZoneIds();
        String nowDateTime =date2String("yyyy-MM-dd HH:mm:ss");
        System.out.println("The time Asia/Shanhai is " + nowDateTime);//程序本地運行所在時區爲[Asia/Shanhai]
        //顯示世界每一個時區當前的實際時間
        for(int i=0;i <ids.length;i++){
            System.out.println(" * " + ids[i] + "=" + string2TimezoneDefault(nowDateTime,ids[i])); 
        }
        //顯示程序運行所在地的時區
        System.out.println("TimeZone.getDefault().getID()=" +TimeZone.getDefault().getID());
    }

    /**
     * 將日期時間字符串根據轉換爲指定時區的日期時間.
     * 
     * @param srcFormater
     *            待轉化的日期時間的格式.
     * @param srcDateTime
     *            待轉化的日期時間.
     * @param dstFormater
     *            目標的日期時間的格式.
     * @param dstTimeZoneId
     *            目標的時區編號.
     * 
     * @return 轉化後的日期時間.
     */
    public static String string2Timezone(String srcFormater,
            String srcDateTime, String dstFormater, String dstTimeZoneId) {
        if (srcFormater == null || "".equals(srcFormater))
            return null;
        if (srcDateTime == null || "".equals(srcDateTime))
            return null;
        if (dstFormater == null || "".equals(dstFormater))
            return null;
        if (dstTimeZoneId == null || "".equals(dstTimeZoneId))
            return null;
        SimpleDateFormat sdf = new SimpleDateFormat(srcFormater);
        try {
            int diffTime = getDiffTimeZoneRawOffset(dstTimeZoneId);
            Date d = sdf.parse(srcDateTime);
            long nowTime = d.getTime();
            long newNowTime = nowTime - diffTime;
            d = new Date(newNowTime);
            return date2String(dstFormater, d);
        } catch (ParseException e) {
            Log.output(e.toString(), Log.STD_ERR);
            return null;
        } finally {
            sdf = null;
        }
    }

    /**
     * 獲取系統當前默認時區與UTC的時間差.(單位:毫秒)
     * 
     * @return 系統當前默認時區與UTC的時間差.(單位:毫秒)
     */
    private static int getDefaultTimeZoneRawOffset() {
        return TimeZone.getDefault().getRawOffset();
    }

    /**
     * 獲取指定時區與UTC的時間差.(單位:毫秒)
     * 
     * @param timeZoneId
     *            時區Id
     * @return 指定時區與UTC的時間差.(單位:毫秒)
     */
    private static int getTimeZoneRawOffset(String timeZoneId) {
        return TimeZone.getTimeZone(timeZoneId).getRawOffset();
    }

    /**
     * 獲取系統當前默認時區與指定時區的時間差.(單位:毫秒)
     * 
     * @param timeZoneId
     *            時區Id
     * @return 系統當前默認時區與指定時區的時間差.(單位:毫秒)
     */
    private static int getDiffTimeZoneRawOffset(String timeZoneId) {
        return TimeZone.getDefault().getRawOffset()
                - TimeZone.getTimeZone(timeZoneId).getRawOffset();
    }

    /**
     * 將日期時間字符串根據轉換爲指定時區的日期時間.
     * 
     * @param srcDateTime
     *            待轉化的日期時間.
     * @param dstTimeZoneId
     *            目標的時區編號.
     * 
     * @return 轉化後的日期時間.
     * @see #string2Timezone(String, String, String, String)
     */
    public static String string2TimezoneDefault(String srcDateTime,
            String dstTimeZoneId) {
        return string2Timezone("yyyy-MM-dd HH:mm:ss", srcDateTime,
                "yyyy-MM-dd HH:mm:ss", dstTimeZoneId);
    }

}

本文轉自:http://stephen830.iteye.com/blog/260343服務器

相關文章
相關標籤/搜索