`
stephen830
  • 浏览: 3010595 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

java对世界各个时区(TimeZone)的通用转换处理方法

    博客分类:
  • java
阅读更多
★★★ 本篇为原创,需要引用转载的朋友请注明:《 http://stephen830.iteye.com/blog/260343 》 谢谢支持!★★★

在进行国际性软件项目开发的过程中,有时候会碰到一些比较特殊的要求。比如:比如说,你做的是个购物网站(假设服务器放在中国上海),当全世界客户在你的网站上下订单买东西后,往往希望看到客户所在地下单时间,比如说我是个美国纽约人,我在你的网站上下单后,你给我看到一个上海的下单时间,会觉得非常的奇怪。众所周知,纽约时间相对上海时间大约要晚13小时,如果让客户看到本地时区的时间,将变得更加符合客户的时间观念,使得客户理解比较方便。

其实,java中早已考虑过世界时区(TimeZone)这个问题,并给出了比较合理的解决方法,可以比较方便的进行世界时区时间的转化,将一个时区的时间转换成另一个时区的时间。可以看看下面的的实际例子(运行例子的main()方法)。

关于如何知道客户所在的时区,可以根据客户所在的ip或者用户注册提供的国家来计算出所在的时区。

/*
 * 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);
    }

}





-------------------------------------------------------------
分享知识 分享快乐, 希望文章能给需要的朋友带来小小的帮助。

另外,欢迎朋友转载,转载时请注明出处,谢谢!


8
0
分享到:
评论
3 楼 BeMyself_wangl 2011-09-29  
字体颜色: [color=red]文字 提示:您可以使用 color=#FF0000[/color][size=small][/size][align=left][/align]
2 楼 inpower 2010-01-19  
stephen830 写道

你说的第3步实现的关键还在于要确定用户所在的时区。

第三步js直接new date中getTime就可以获取
1 楼 stephen830 2008-11-01  
jacklondon 写道

可能这样会比较好:1. 数据库中时间,都用 GMT 时间。2. 页面显示,用自定义 GMT_time JSP tag lib 显示。所有页面都用这个 tag lib.3. 用户录入的时间,保存前转换成 GMT 时间。4. http session 中,最好不要保存 时间数据。麻烦的是第三步,写起来麻烦。


你说的第3步实现的关键还在于要确定用户所在的时区。

相关推荐

    Util.java 一些公共的Java方法

    通过`TimeZone.getTimeZone()`方法获取时间区对象,这对于处理跨时区的数据非常有用,特别是在进行国际化的应用开发中,确保日期时间的正确显示和计算。 #### b. 日期格式化 `DEFAULT_DATE_FORMAT_STRING`定义了一...

    Java时区转换实例代码解析

    Java时区转换是Java开发中处理时间问题的关键部分,尤其在全球化应用中显得尤为重要。时区转换涉及到地球上的不同地理位置如何以不同的时间表示同一事件。本文将深入探讨时区的概念,时间的表示方式,时间戳的含义,...

    java日期对象练习

    - `TimeZone`类用来处理不同时区。`TimeZone.getDefault()`获取默认时区,`TimeZone.getTimeZone("Asia/Shanghai")`获取上海时区。 - Java 8的`ZonedDateTime`类提供了时区支持,例如`ZonedDateTime zdt = ...

    一个功能完备的java日历

    Java日历考虑了不同的时区和语言环境,`getTimeZone()`和`setTimeZone(TimeZone tz)`方法用于处理时区,`getFirstDayOfWeek()`和`setFirstDayOfWeek(int value)`等方法则可以调整一周的起始日。 7. **农历与万年历...

    java.util.pdf

    在java.util包中,包含了一些Java集合框架的基础类,比如Enumeration、Hashtable、Stack、Vector等,以及日期和时间处理相关的类,如Calendar、Date、TimeZone等。同时,提及了Timer和TimerTask,它们用于任务调度,...

    时间戳转换工具.rar

    这就需要用到时区转换功能,如Java的`ZoneId`,Python的`pytz`库,或者JavaScript的`Intl.DateTimeFormat`的`timeZone`选项。 总的来说,"时间戳转换工具"对于IT从业者来说是一个非常实用的辅助工具,它可以极大地...

    Java时间函数大全[归类].pdf

    9. **时区处理**:`java.util.TimeZone`类用于处理时区,可以根据时区ID获取相应的时区对象。`ZonedDateTime`类则提供了与特定时区相关的日期时间操作。 10. **闰年判断**:`isLeapYear`函数用于判断给定年份是否为...

    异常:java.sql.SQLException: The server time zone value ‘?й???????’ is unrecognized or represents more

    1. 如果`serverTimezone`是URL中的第一个参数,你可以将连接字符串修改为: ``` url=jdbc:mysql://localhost:3306/mybatis?serverTimezone=GMT ``` 2. 如果`serverTimezone`不是第一个参数,确保它被正确地插入...

    28个java常用的工具类

    28. **`java.util.TimeZone`**: 处理时区信息。 以上这些工具类构成了Java程序员日常开发的基础工具箱,它们的强大功能使得开发者能够更高效、更简洁地编写代码。了解并熟练运用这些工具类,可以显著提升编程效率和...

    DateUtil(通用日期工具类)

    日期和时间操作通常与时区有关,DateUtil可能包含处理时区的方法,如`toTimeZone(Date date, TimeZone toZone)`,将日期转换为指定时区的时间。 8. **日期间隔计算**: `getDaysBetween(Date startDate, Date ...

    编程中通用解决日期时间组合问题

    Python的pytz库,Java的ZoneId和ZoneOffset,JavaScript的Intl.DateTimeFormat的`timeZone`选项都能帮助你进行时区转换。 7. **日期时间的计算**:除了基本的比较和格式化,我们还经常需要计算日期时间的差值,如...

    Java中Date,Calendar,Timestamp的区别以及相互转换与使用

    - TIMESTAMP WITH TIME ZONE 和 TIMESTAMP WITH LOCAL TIME ZONE 用于处理时区信息。 在实际编程中,选择使用哪种类主要取决于需求的精度和场景。如果只需要日期,可以选择 `java.sql.Date`;如果需要精确到毫秒,...

    Calendar.zip_Java编程_Java_

    5. **时区处理**: `java.util.TimeZone`用于处理时区信息,`java.time.ZoneId`在新API中替代了它,提供了更好的时区支持。 6. **日期时间运算**: 包括添加、减去日期时间、比较日期等,可以通过`plus()`, `minus()`,...

    Gmt

    在编程语言如Java、Python等中,处理时间时,经常会遇到与GMT相关的函数或类,例如Java的`java.util.TimeZone`中的`getTimeZone("GMT")`,用于获取GMT时区对象。 在文件系统中,文件的修改、创建和访问时间戳通常会...

    oracle数据类型和对应的JDBC类型.docx

    - `TIMESTAMP WITH TIME ZONE` 和 `TIMESTAMP WITH LOCAL TIME ZONE`:Oracle 的带时区的时间戳类型,映射为特定的 Oracle 类型如 `oracle.sql.TIMESTAMPTZ` 和 `oracle.sql.TIMESTAMPLTZ`。 5. **二进制类型**: ...

    System.currentTimeMillis()计算方式与时间的单位转换详解

    formatter.setTimeZone(TimeZone.getTimeZone("Asia/Shanghai")); String formattedTime = formatter.format(new Date(currentTimeMillis)); System.out.println("当前时间(中国时区):" + formattedTime); ``` ...

    时间处理函数工具分享(时间戳计算)

    `TimeZone.getDefault()` 用于获取系统默认的时区。 `java.text.SimpleDateFormat` 类则用于日期和时间的格式化和解析。例如,`"yyyy-MM-dd HH:mm:ss"` 是一个常见的日期时间格式,可以使用 `SimpleDateFormat` 的 ...

    公历

    `GregorianCalendar`还支持时区转换,通过`setTimeZone`方法可以改变日历的时间区域设置。 ```java TimeZone timeZone = TimeZone.getTimeZone("Asia/Shanghai"); calendar.setTimeZone(timeZone); ``` 总结,`...

    面试大数据岗位 spark相关问题汇总

    - 修改`oozie-site.xml`中的配置项`oozie.processing.timezone`为对应的时区,例如`GMT+0800`。 - 如果是通过数据库连接,可以在连接字符串中添加`serverTimezone`参数,如`dbConn="jdbc:mysql://101.200.230.0:...

Global site tag (gtag.js) - Google Analytics