`

java时区问题

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


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

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

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



Java代码  01./* 
02. * Created on 2005-6-10 
03. * Author stephen 
04. * Email zhoujianqiang AT gmail DOT com 
05. * CopyRight(C)2005-2008 , All rights reserved. 
06. */ 
07.package com.soft4j.utility;  
08. 
09.import java.text.ParseException;  
10.import java.text.SimpleDateFormat;  
11.import java.util.Date;  
12.import java.util.GregorianCalendar;  
13.import java.util.TimeZone;  
14.import java.util.Vector;  
15. 
16.import com.soft4j.log.Log;  
17. 
18./** 
19. * 与日期、时间相关的一些常用工具方法. 
20. * <p> 
21. * 日期(时间)的常用格式(formater)主要有: <br> 
22. * yyyy-MM-dd HH:mm:ss <br> 
23. *  
24. * @author stephen 
25. * @version 1.0.0 
26. */ 
27.public final class DateTool {  
28. 
29.    /** 
30.     * 对日期(时间)中的日进行加减计算. <br> 
31.     * 例子: <br> 
32.     * 如果Date类型的d为 2005年8月20日,那么 <br> 
33.     * calculateByDate(d,-10)的值为2005年8月10日 <br> 
34.     * 而calculateByDate(d,+10)的值为2005年8月30日 <br> 
35.     *  
36.     * @param d 
37.     *            日期(时间). 
38.     * @param amount 
39.     *            加减计算的幅度.+n=加n天;-n=减n天. 
40.     * @return 计算后的日期(时间). 
41.     */ 
42.    public static Date calculateByDate(Date d, int amount) {  
43.        return calculate(d, GregorianCalendar.DATE, amount);  
44.    }  
45.      
46.    public static Date calculateByMinute(Date d, int amount) {  
47.        return calculate(d, GregorianCalendar.MINUTE, amount);  
48.    }  
49.      
50.    public static Date calculateByYear(Date d, int amount) {  
51.        return calculate(d, GregorianCalendar.YEAR, amount);  
52.    }  
53. 
54.    /** 
55.     * 对日期(时间)中由field参数指定的日期成员进行加减计算. <br> 
56.     * 例子: <br> 
57.     * 如果Date类型的d为 2005年8月20日,那么 <br> 
58.     * calculate(d,GregorianCalendar.YEAR,-10)的值为1995年8月20日 <br> 
59.     * 而calculate(d,GregorianCalendar.YEAR,+10)的值为2015年8月20日 <br> 
60.     *  
61.     * @param d 
62.     *            日期(时间). 
63.     * @param field 
64.     *            日期成员. <br> 
65.     *            日期成员主要有: <br> 
66.     *            年:GregorianCalendar.YEAR <br> 
67.     *            月:GregorianCalendar.MONTH <br> 
68.     *            日:GregorianCalendar.DATE <br> 
69.     *            时:GregorianCalendar.HOUR <br> 
70.     *            分:GregorianCalendar.MINUTE <br> 
71.     *            秒:GregorianCalendar.SECOND <br> 
72.     *            毫秒:GregorianCalendar.MILLISECOND <br> 
73.     * @param amount 
74.     *            加减计算的幅度.+n=加n个由参数field指定的日期成员值;-n=减n个由参数field代表的日期成员值. 
75.     * @return 计算后的日期(时间). 
76.     */ 
77.    private static Date calculate(Date d, int field, int amount) {  
78.        if (d == null)  
79.            return null;  
80.        GregorianCalendar g = new GregorianCalendar();  
81.        g.setGregorianChange(d);  
82.        g.add(field, amount);  
83.        return g.getTime();  
84.    }  
85. 
86.    /** 
87.     * 日期(时间)转化为字符串. 
88.     *  
89.     * @param formater 
90.     *            日期或时间的格式. 
91.     * @param aDate 
92.     *            java.util.Date类的实例. 
93.     * @return 日期转化后的字符串. 
94.     */ 
95.    public static String date2String(String formater, Date aDate) {  
96.        if (formater == null || "".equals(formater))  
97.            return null;  
98.        if (aDate == null)  
99.            return null;  
100.        return (new SimpleDateFormat(formater)).format(aDate);  
101.    }  
102. 
103.    /** 
104.     * 当前日期(时间)转化为字符串. 
105.     *  
106.     * @param formater 
107.     *            日期或时间的格式. 
108.     * @return 日期转化后的字符串. 
109.     */ 
110.    public static String date2String(String formater) {  
111.        return date2String(formater, new Date());  
112.    }  
113.      
114.    /** 
115.     * 获取当前日期对应的星期数. 
116.     * <br>1=星期天,2=星期一,3=星期二,4=星期三,5=星期四,6=星期五,7=星期六 
117.     * @return 当前日期对应的星期数 
118.     */ 
119.    public static int dayOfWeek() {  
120.        GregorianCalendar g = new GregorianCalendar();  
121.        int ret = g.get(java.util.Calendar.DAY_OF_WEEK);  
122.        g = null;  
123.        return ret;  
124.    }  
125. 
126. 
127.    /** 
128.     * 获取所有的时区编号. <br> 
129.     * 排序规则:按照ASCII字符的正序进行排序. <br> 
130.     * 排序时候忽略字符大小写. 
131.     *  
132.     * @return 所有的时区编号(时区编号已经按照字符[忽略大小写]排序). 
133.     */ 
134.    public static String[] fecthAllTimeZoneIds() {  
135.        Vector v = new Vector();  
136.        String[] ids = TimeZone.getAvailableIDs();  
137.        for (int i = 0; i < ids.length; i++) {  
138.            v.add(ids[i]);  
139.        }  
140.        java.util.Collections.sort(v, String.CASE_INSENSITIVE_ORDER);  
141.        v.copyInto(ids);  
142.        v = null;  
143.        return ids;  
144.    }  
145. 
146.    /** 
147.     * 测试的main方法. 
148.     *  
149.     * @param argc 
150.     */ 
151.    public static void main(String[] argc) {  
152.          
153.        String[] ids = fecthAllTimeZoneIds();  
154.        String nowDateTime =date2String("yyyy-MM-dd HH:mm:ss");  
155.        System.out.println("The time Asia/Shanhai is " + nowDateTime);//程序本地运行所在时区为[Asia/Shanhai]  
156.        //显示世界每个时区当前的实际时间  
157.        for(int i=0;i <ids.length;i++){  
158.            System.out.println(" * " + ids[i] + "=" + string2TimezoneDefault(nowDateTime,ids[i]));   
159.        }  
160.        //显示程序运行所在地的时区  
161.        System.out.println("TimeZone.getDefault().getID()=" +TimeZone.getDefault().getID());  
162.    }  
163. 
164.    /** 
165.     * 将日期时间字符串根据转换为指定时区的日期时间. 
166.     *  
167.     * @param srcFormater 
168.     *            待转化的日期时间的格式. 
169.     * @param srcDateTime 
170.     *            待转化的日期时间. 
171.     * @param dstFormater 
172.     *            目标的日期时间的格式. 
173.     * @param dstTimeZoneId 
174.     *            目标的时区编号. 
175.     *  
176.     * @return 转化后的日期时间. 
177.     */ 
178.    public static String string2Timezone(String srcFormater,  
179.            String srcDateTime, String dstFormater, String dstTimeZoneId) {  
180.        if (srcFormater == null || "".equals(srcFormater))  
181.            return null;  
182.        if (srcDateTime == null || "".equals(srcDateTime))  
183.            return null;  
184.        if (dstFormater == null || "".equals(dstFormater))  
185.            return null;  
186.        if (dstTimeZoneId == null || "".equals(dstTimeZoneId))  
187.            return null;  
188.        SimpleDateFormat sdf = new SimpleDateFormat(srcFormater);  
189.        try {  
190.            int diffTime = getDiffTimeZoneRawOffset(dstTimeZoneId);  
191.            Date d = sdf.parse(srcDateTime);  
192.            long nowTime = d.getTime();  
193.            long newNowTime = nowTime - diffTime;  
194.            d = new Date(newNowTime);  
195.            return date2String(dstFormater, d);  
196.        } catch (ParseException e) {  
197.            Log.output(e.toString(), Log.STD_ERR);  
198.            return null;  
199.        } finally {  
200.            sdf = null;  
201.        }  
202.    }  
203. 
204.    /** 
205.     * 获取系统当前默认时区与UTC的时间差.(单位:毫秒) 
206.     *  
207.     * @return 系统当前默认时区与UTC的时间差.(单位:毫秒) 
208.     */ 
209.    private static int getDefaultTimeZoneRawOffset() {  
210.        return TimeZone.getDefault().getRawOffset();  
211.    }  
212. 
213.    /** 
214.     * 获取指定时区与UTC的时间差.(单位:毫秒) 
215.     *  
216.     * @param timeZoneId 
217.     *            时区Id 
218.     * @return 指定时区与UTC的时间差.(单位:毫秒) 
219.     */ 
220.    private static int getTimeZoneRawOffset(String timeZoneId) {  
221.        return TimeZone.getTimeZone(timeZoneId).getRawOffset();  
222.    }  
223. 
224.    /** 
225.     * 获取系统当前默认时区与指定时区的时间差.(单位:毫秒) 
226.     *  
227.     * @param timeZoneId 
228.     *            时区Id 
229.     * @return 系统当前默认时区与指定时区的时间差.(单位:毫秒) 
230.     */ 
231.    private static int getDiffTimeZoneRawOffset(String timeZoneId) {  
232.        return TimeZone.getDefault().getRawOffset()  
233.                - TimeZone.getTimeZone(timeZoneId).getRawOffset();  
234.    }  
235. 
236.    /** 
237.     * 将日期时间字符串根据转换为指定时区的日期时间. 
238.     *  
239.     * @param srcDateTime 
240.     *            待转化的日期时间. 
241.     * @param dstTimeZoneId 
242.     *            目标的时区编号. 
243.     *  
244.     * @return 转化后的日期时间. 
245.     * @see #string2Timezone(String, String, String, String) 
246.     */ 
247.    public static String string2TimezoneDefault(String srcDateTime,  
248.            String dstTimeZoneId) {  
249.        return string2Timezone("yyyy-MM-dd HH:mm:ss", srcDateTime,  
250.                "yyyy-MM-dd HH:mm:ss", dstTimeZoneId);  
251.    }  
252. 
253.}

分享到:
评论

相关推荐

    java的时区问题

    Java的时区问题是一个复杂而重要的主题,尤其是在全球化的软件开发中。时区涉及到日期、时间的计算,以及与特定地理位置相关的夏令时调整。Java提供了丰富的时区支持,但理解其工作原理对于开发出正确处理时间的软件...

    java.util.TimeZone 的世界时区列表

    ### Java.util.TimeZone的世界时区列表解析 #### 一、概述 `java.util.TimeZone` 是Java标准库中的一个类,用于表示不同时区的信息。本文档提供了通过`java.util.TimeZone`类导出的世界范围内时区列表。该列表不仅...

    java转换时区时间过程详解

    Java时区时间转换过程详解 Java时区时间转换是指将一个时区的时间转换成另一个时区的时间,这个过程需要了解时区的概念和计算方法。在本文中,我们将详细介绍时区的概念、UTC时间、格林尼治时间、夏令时、区时转换...

    java 时区转换工具包

    1. 获取时区时间 public static ZonedDateTime getNow(int offset) 2. 解析指定时间 public static ZonedDateTime parse(String date,String dateFormat,int offset) 3. 获取某一天的零点 public static ...

    系统时间注册表,修正JAVA Eclipise时区问题

    用户的测试机安装的win7,测试时发现时间总是差8个小时。 在win7下装JDK1.4和JDK1.5、eclipse,输出系统时区和时间。...导入本压缩包中国时区注册表.reg 解决2003 WIN7 时区问题。 再有疑问联系,CSDN:lawsystem

    java时区转换的理解及示例详解

    Java时区转换的理解及示例详解 Java时区转换是Java编程语言中一个重要的概念,对于时间相关的操作非常重要。在本文中,我们将详细介绍Java时区转换的理解及示例详解。 一、时区的基本概念 时区是指地球上的一个...

    基于java时区转换夏令时的问题及解决方法

    "基于Java时区转换夏令时的问题及解决方法" 在Java中进行时区转换时,需要了解夏令时的概念和时区的表示方法。夏令时是指在夏天的时候,将时钟拨快一个小时,以提早日光的使用。目前有110多个国家采用夏令时。 ...

    Windows2008上运行java产生8小时时差问题原因

    "Windows2008上运行java产生8小时时差问题原因" 在 Windows 2008 环境中运行 ...解决 8 小时时差问题需要检查 Java 的时区设置问题和 JDK 的版本问题。通过解决这些问题,可以确保 Java 应用程序与系统时间保持一致。

    java国际化&时间处理

    为了解决`SimpleDateFormat`的线程安全问题,Java 8引入了`java.time`包,这是新的日期时间API,包含了`LocalDate`、`LocalTime`、`LocalDateTime`、`ZonedDateTime`等类,它们提供了更强大、更安全、更易于使用的...

    WIN7 JAVA获取时间有问题

    综上所述,解决“WIN7 JAVA获取时间有问题”的关键在于检查Java时区设置、系统时间设置,以及确认Java运行环境与Windows 7的兼容性。如果问题依然存在,参考相关博客或其他在线资源,或者对`timezone.reg`文件进行...

    Java对世界不同时区timezone之间时间转换的处理方法

    在不同时区之间转换时间需要考虑两个问题:获取到源时区相对于GMT的差距(考虑夏令时)和获取到目的时区相对于GMT的差距(考虑夏令时)。基本思路是: 1. 获取到源时区相对于GMT的差距(考虑夏令时)。 2. 获取到...

    Java完成UTC与BJT时区的转换

    Java初学者练习题,使用if else循环完成,可对初学者提供一定的参考。

    Java时区转换实例代码解析

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

    关于Java中的mysql时区问题详解

    "Java 中的 MySQL 时区问题详解" Java 中的 MySQL 时区问题是一种常见的问题,尤其是在分布式系统中,对时区的处理尤为重要。本文将详细介绍 Java 中的 MySQL 时区问题,并通过示例代码进行讲解。 一、时区问题的...

    java中 new date() 打印出的时间与系统时间错了八小时的解决方法

    总的来说,Java中`new Date()` 出现时间差的问题主要源于时区设置,可以通过调整JVM时区或者在代码中设定时区来解决。同时,不要忽视操作系统自身的时区设置,因为它可能会影响到其他非Java程序的时间显示。理解并...

    Java处理时区的注意事项

    这可能会导致问题,特别是当数据在不同时区之间传递时。因此,在启动应用程序时,通常建议显式设置JVM的默认时区,例如:`TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"))`,这样可以确保系统在处理...

Global site tag (gtag.js) - Google Analytics