浅解 JAVA与时区

时区转换

主要介绍一下 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个国家每年要实行夏令时。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,163评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,301评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,089评论 0 352
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,093评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,110评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,079评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,005评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,840评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,278评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,497评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,394评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,980评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,628评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,796评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,649评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,548评论 2 352

推荐阅读更多精彩内容

  • 如果不注意,大概很多人认为“闰月”与“闰年”是一个意思,其实不是,虽说只是一字之差,所包含的意思却相差很远。 “闰...
    雨落未惊风阅读 8,201评论 1 1
  • 一、Linux时间类型 在Linux系统当中,时间分为两种类型:格林威治时间和日历时间。 Coordinated ...
    konishi5202阅读 3,455评论 0 4
  • Django时间问题 在用django1.8版本做项目的时候遇到时间的存储与读取不一致的问题,网上找了很多帖子,但...
    技术创造未来阅读 4,567评论 0 1
  • 时钟概念 (1)UTC 整个地球分为二十四时区,每个时区都有自己的本地时间。在国际无线电通信场合,为了统一起见,使...
    Bogon阅读 34,948评论 1 7
  • 今日作业 1、A、B、C账号的定位 2、个人讲课的文字稿 A号:主号:计划做冷吃兔社群人群转化变现 -------...
    Rock567阅读 317评论 0 0