美文网首页Java程序员
浅解 JAVA与时区

浅解 JAVA与时区

作者: 迷路的老山羊 | 来源:发表于2019-03-06 17:09 被阅读107次

    时区转换

    主要介绍一下 Java 时区转换相关的一些概念,和转换示例。

    由于夏令时的存在,应该通过Java 或者 DB 提供的方法来转换。

    JAVA 时间的时区转换

    Java Date 支持 UTC 时间

    世界标准时间:2018-01-31T14:32:19Z
    T 表示后面跟着时间,Z 表示时区为 0 时区

    本地时间,也叫不含时区信息的时间,末尾没有Z
    2018-01-31T14:32:19

    Java 时区 java.util.TimeZone 类

    TimeZone 表示时区偏移量,也可以计算夏令时。
    可以通过 getDefault 获取当前系统时区例如,对于在中国运行的程序,getDefault 基于中国标准时间创建 TimeZone 对象。

    也可使用getTimeZone来获取某个时区 ID 的 TimeZone。例如美国太平洋时区的时区 ID 是 "America/Los_Angeles"。因此,可以使用下面语句获得美国太平洋时间 TimeZone 对象:
    TimeZone tz = TimeZone.getTimeZone("America/Los_Angeles");通过 getAvailableIDs 方法获取所有受支持的时区 ID (时区 map 保存在 ZoneInfoFile 类中) ,通过这些 ID 可以正确转换时区(包括夏令时的计算)。

    如果想要的时区无法用受支持的 ID 之一表示,那么可以指定自定义时区 ID 来生成 TimeZone。自定义时区 ID 的语法是:
    CustomID:
    GMT Sign Hours : Minutes
    GMT Sign Hours Minutes
    GMT Sign Hours
    Sign: 下面之一
    + -
    Hours:
    Digit
    Digit Digit
    Minutes:
    Digit Digit
    Digit: 下面之一
    0 1 2 3 4 5 6 7 8 9
    Hours 必须在 0 至 23 之间,Minutes 必须在 00 至 59 之间。例如,"GMT+10" 和 "GMT+0010" 分别意味着比 GMT 提前 10 小时和 10 分钟。

    格式是与区域无关的,并且数字必须取自 Unicode 标准的 Basic Latin 块。没有夏令时转换安排可以用自定义时区 ID 指定。如果指定的字符串与语法不匹配,就使用 "GMT"。

    Java 时区转换

    SimpleDateFormat

        String timeSummer = "2019-03-10 09:00:00"; //字面时间
        String timeSummer1 = "2019-03-10 10:00:00"; //字面时间
        // 设置为 GMT 时间
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
        Date date9 =  dateFormat.parse(timeSummer);
        Date date10 = dateFormat.parse(timeSummer1);
        // timeSummer,timeSummer1的当前时区时间
        System.out.println(TimeZone.getDefault().getDisplayName() + "," + date9);
        System.out.println(TimeZone.getDefault().getDisplayName() + "," + date10);
        // timeSummer,timeSummer1的太平洋时区时间,转换夏令时
        dateFormat.setTimeZone(TimeZone.getTimeZone("America/Los_Angeles"));
        System.out.println(dateFormat.getTimeZone().getDisplayName() + "," + dateFormat.format(date9));
        System.out.println(dateFormat.getTimeZone().getDisplayName()+ "," + dateFormat.format(date10));
        // timeSummer,timeSummer1的自定义时区时间,没有转换夏令时
        dateFormat.setTimeZone(TimeZone.getTimeZone("GMT-08:00"));
        System.out.println(dateFormat.getTimeZone().getDisplayName() + "," + dateFormat.format(date9));
        System.out.println(dateFormat.getTimeZone().getDisplayName() + "," + dateFormat.format(date10));
    

    运行结果:

    China Standard Time,Sun Mar 10 17:00:00 CST 2019
    China Standard Time,Sun Mar 10 18:00:00 CST 2019
    Pacific Standard Time,2019-03-10 01:00:00
    Pacific Standard Time,2019-03-10 03:00:00
    GMT-08:00,2019-03-10 01:00:00
    GMT-08:00,2019-03-10 02:00:00
    

    ZonedDateTime

    参考资料

        LocalDateTime localDateTime =    LocalDateTime.now();
        // 无时区的本地时间
        System.out.println(localDateTime);
        System.out.println(LocalDateTime.now(ZoneId.of("America/New_York")));
        // 向本地时间添加时区
        System.out.println(localDateTime.atZone(ZoneId.of("America/New_York")));
        System.out.println(ZonedDateTime.of(localDateTime, ZoneId.of("America/New_York")));
        // 从 ZoneDateTime 获取不同时区的时间
        System.out.println(new Date(0));
        System.out.println(ZonedDateTime.ofInstant(new Date(0).toInstant(), ZoneId.of("GMT")));
        System.out.println(ZonedDateTime.ofInstant(new Date(0).toInstant(), ZoneId.of("America/New_York")));
        ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(new Date(0).toInstant(), ZoneId.of("GMT"));
        System.out.println(zonedDateTime.withZoneSameInstant(ZoneId.of("America/New_York")));
        System.out.println(zonedDateTime.withZoneSameInstant(ZoneId.of("GMT+08:00")));
    

    MySQL convert_tz() 时区转换函数

    CONVERT_TZ(dt,from_tz,to_tz) 转换datetime值dt,从 from_tz 由给定转到 to_tz 时区给出的时区,并返回的结果值。 如果参数无效该函数返回NULL。

    mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','GMT','MET');  
    +---------------------------------------------------------+  
    | CONVERT_TZ('2004-01-01 12:00:00','GMT','MET')           |  
    +---------------------------------------------------------+  
    | 2004-01-01 13:00:00                                     |  
    +---------------------------------------------------------+  
    1 row in set (0.00 sec)  
    
    mysql> SELECT CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00');  
    +---------------------------------------------------------+  
    | CONVERT_TZ('2004-01-01 12:00:00','+00:00','+10:00')     |  
    +---------------------------------------------------------+  
    | 2004-01-01 22:00:00                                     |  
    +---------------------------------------------------------+  
    1 row in set (0.00 sec)
    

    Unix时间戳

    Unix的时间戳都是1970年1月1日0时0分0秒开始到现在的秒数。

    起点1970-01-01T00:00:00 指的是 GMT 时间,Unix时间戳是 0,在中国北京时区时间为1970-01-01 T08:00:00, 在美国纽约时间为 1969-12-31T16:00:00。

    TimeZone 时区

    理论时区以被15整除的子午线为中心,向东西两侧延伸7.5度,即每15°划分一个时区,划分24个时区。
    为了避开国界线,划分了法定时区--时区列表

    TAI UT UTC GMT 时间

    UT Universal Time

    世界时,一种以格林尼治子夜起算的平太阳时。世界时从 UT0 开始,修正到 UT1、UT2。UT 的1s为全年内每日平均长度的1/8.64×104,由于天体运动不规律,比如地球本身自转速度不均匀,导致时间长度不均匀。

    GMT Greenwich Mean Time

    格林威治标准时间,平均太阳时。
    GMT 时间在1972年之前与世界时( UT )相同,1972年后 GMT 不在作为时间标准。现在 GMT 是一个时区(GMT 0:00 格林尼治标准时间)。

    UTC Coordinated Universal Time

    世界协调时,是当今最主要的世界时间标准,以原子时秒长为基础。为确保 UTC 与世界时相差不会超过 0.9 秒,在有需要的情况下会在协调世界时内加上正或负闰秒。因此协调世界时与国际原子时之间会出现若干整数秒的差别。位于巴黎的国际地球自转事务中央局负责决定何时加入闰秒,一般会在每年的 6 月 30 日、12 月 31 日的最后一秒进行调整。

    Leap Second 闰秒

    闰秒,是指为保持协调世界时接近于世界时时刻,由国际计量局统一规定在年底或年中(也可能在季末)对协调世界时增加或减少1秒的调整。由于地球自转的不均匀性和长期变慢性(主要由潮汐摩擦引起的),会使世界时(民用时)和原子时之间相差超过到±0.9秒时,就把协调世界时向前拨1秒(负闰秒,最后一分钟为59秒)或向后拨1秒(正闰秒,最后一分钟为61秒); 闰秒一般加在公历年末或公历六月末。

    Unix time (Unix 时间戳)

    从协调世界时1970年1月1日0时0分0秒起至现在的总秒数,不考虑闰秒。即Unix不存在闰秒。

    NTP Network Time Protocal

    计算机时间同步化的一种协议,它可以使计算机对其服务器或时钟源(如石英钟,GPS等等)做同步化,它可以提供高精准度的时间校正(LAN上与标准间差小于1毫秒,WAN上几十毫秒),且可介由加密确认的方式来防止恶毒的协议攻击。时间按NTP服务器的等级传播。按照离外部UTC源的远近把所有服务器归入不同的Stratum(层)中。

    谷歌将修改其NTP服务器,使之在闰秒前、后各10小时的期限内时钟频率降低0.0014%。自2008年的闰秒以来,谷歌一直使用这一技术。

    闰秒扫盲

    Daylight Saving Time:DST

    夏令时,又称“日光节约时制”或“夏时制”,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为“夏令时间”。一般在天亮早的夏季人为将时间提前一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电。各个采纳夏令时的国家具体规定不同。目前全世界有近110个国家每年要实行夏令时。

    相关文章

      网友评论

        本文标题:浅解 JAVA与时区

        本文链接:https://www.haomeiwen.com/subject/qtsxpqtx.html