• JAVA时区处理(转)


    说起java中的时间,大家或许都很熟悉,朗朗上口的Date、Calendar、SimpleDateFormat等。但是大家对他们的认识真的很深刻吗?今天我要想大家说的是TimeZone,即时区。

      经常有人发现时间不对,比如相差8个小时等等,其真实原因便是TimeZone.只有正确合理的运用TimeZone,才能保证系统时间无论何时都是准确的。

      影响TimeZone的因素:

      1、操作系统的时区设置。

      2、数据传输时时区设置。

      第一个原因其实是根本原因,当数据在不同操作系统间流转时,就有可能因为操作系统的差异造成时间偏差,而JVM默认情况下获取的就是操作系统的时区设置。因此在项目中最好事先设置好时区,例如:

      TimeZone.setDefault(TimeZone.getTimeZone("Asia/Shanghai"));

      那么一旦时区设置不同导致时间有偏差怎么办?如何转化呢?

      ● 用SimpleDateFormat的话,如下:

      public static void main(String[] args) {

      Date date = new Date(1359641834000L);// 2013-1-31 22:17:14

      String dateStr = "2013-1-31 22:17:14";

      SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

      dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));

      try {

      Date dateTmp = dateFormat.parse(dateStr);

      System.out.println(dateTmp);

      } catch (ParseException e) {

      e.printStackTrace();

      }

      String dateStrTmp = dateFormat.format(date);

      System.out.println(dateStrTmp);

      }

      运行结果:

      Fri Feb 01 06:17:14 CST 2013

      2013-01-31 14:17:14

      我们发现同一时间,字符串和日期运行出来的结果并不相同,那么我们应该怎么理解呢?一切都要以当前操作系统的时间为基准。我的操作系统是"Asia/Shanghai",即GMT+8的北京时间,那么执行日期转字符串的format方法时,由于日期生成时默认是操作系统时区,因此2013-1-31 22:17:14是北京时间,那么推算到GMT时区,自然是要减8个小时的;而执行字符串转日期的parse方法时,由于字符串本身没有时区的概念,因此2013-1-31 22:17:14就是指GMT(UTC)时间【ps:所有字符串都看做是GMT时间】,那么当转化为日期时要加上默认时区,即"Asia/Shanghai",因此要加上8个小时。

      ● 用Calendar的话,如下:

      public static void main(String[] args) {

      Date date = new Date(1359641834000L);// 2013-1-31 22:17:14

      System.out.println(date);

      Calendar calendar = Calendar.getInstance();

      calendar.setTimeZone(TimeZone.getTimeZone("GMT"));

      // 或者可以 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

      calendar.setTime(date);

      System.out.println(calendar.get(Calendar.HOUR_OF_DAY) + ":" + calendar.get(Calendar.MINUTE));

      }

      运行结果:

      Thu Jan 31 22:17:14 CST 2013

      14:17

      Calendar不涉及到日期与字符串的转化,因此不像SimpleDateFormat那么复杂,与日期转字符串的思路类似。但是需要注意的是,设置完时区后,我们不能用calendar.getTime()来直接获取Date日期,因此此时的日期与一开始setTime时是相同值,要想获取某时区的时间,正确的做法是用calendar.get()方法,那么我们怎么获得Date类型的日期呢?

      正确的做法如下:

      public static void main(String[] args) {

      Date date = new Date(1359641834000L);

      System.out.println(date);

      Calendar calendar = Calendar.getInstance();

      calendar.setTimeZone(TimeZone.getTimeZone("GMT"));

      // 或者可以 Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT"));

      calendar.setTime(date);

      Calendar calendar2 = Calendar.getInstance();

      calendar2.set(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH), calendar.get(Calendar.HOUR_OF_DAY), calendar.get(Calendar.MINUTE), calendar.get(Calendar.SECOND));

      System.out.println(calendar2.getTime());

      }

      运行结果:

      Thu Jan 31 22:17:14 CST 2013

      Thu Jan 31 14:17:14 CST 2013

      ● 完美通用转换方法

      其实上面两个转换方法都要受到操作系统的时区设置影响,如果软件在不同操作系统运行,仍然会有时间误差,那么怎么才能统一呢?

      public static void main(String[] args) {

      Date date = new Date(1359641834000L);

      System.out.println(date);

      date = changeTimeZone(date, TimeZone.getTimeZone("Asia/Shanghai"), TimeZone.getTimeZone("GMT"));

      System.out.println(date);

      }

      /**

      * 获取更改时区后的日期

      * @param date 日期

      * @param oldZone 旧时区对象

      * @param newZone 新时区对象

      * @return 日期

      */

      public static Date changeTimeZone(Date date, TimeZone oldZone, TimeZone newZone) {

      Date dateTmp = null;

      if (date != null) {

      int timeOffset = oldZone.getRawOffset() - newZone.getRawOffset();

      dateTmp = new Date(date.getTime() - timeOffset);

      }

      return dateTmp;

      }

      运行结果:

      Thu Jan 31 22:17:14 CST 2013

      Thu Jan 31 14:17:14 CST 2013

      通过以上可以看出时区确实有不少需要我们注意和专研的地方,其实这并不是什么高深的东西,也是java日期里的基础,我认为盲目学习各种开源框架并不能成为真正的高手,框架也是基于jdk的基础上开发而来的,不懂jdk的基本知识,想真正提高到架构师的级别是非常苦难的,因此基础很重要,掌握jdk基本功确实是成为"大侠"的前提条件,共同努力吧!

  • 相关阅读:
    JS在ff和ie区别(未完,待续...)
    得出一年中已过的天数
    div高度随浏览器变化
    offsetTop,offsetLeft
    完美的DIV三行三列自适应高度布局
    YUI Compressor
    Android repo 出现error.GitError: manifests revlist ('^12303f87b9f90c07bf4aec4c4353ba514ee70c8a', 'HEAD', ''): fatal: bad revision 'HEAD'
    1、ECharts(中国地图篇)的使用
    2012年新浪微博用户密码泄露漏洞(图片解析)
    铁道部购票网站可能造成另一次的密码危机(转)
  • 原文地址:https://www.cnblogs.com/longzhaoyu/p/3370171.html
Copyright © 2020-2023  润新知