发布时间:2023-01-29 文章分类:编程知识 投稿人:赵颖 字号: 默认 | | 超大 打印

什么是时区?

时区介绍

1884年在华盛顿召开的一次国际经度会议(又称国际子午线会议)上,规定将全球划分为24个时区(东、西各12个时区)。规定英国(格林尼治天文台旧址)为中时区(零时区)、东1-12区,西1-12区。每个时区横跨经度15度,时间正好是1小时。

时区的分类?

理论时区

上述时区定义其实是理论时区。理论时区的时间采用其中央经线(或标准经线)的地方时。比如东八区的经度范围是112.5°E~127.5°E,中央经线为120°E。

所以每差一个时区,区时相差一个小时,相差多少个时区,就相差多少个小时。东边的时区时间比西边的时区时间早。

法定时区

复原辽阔的国家,横跨多个时区,常常以国家内部行政分界线为时区界线。这就是实际时区,即法定时区

比如中国的地理区划,西至75°E,东至135°E,横跨多个时区,然而实际上我们国家法定时区为东八区标准时。居住在我国西部,如新疆的同学应该深有感触,北京时间早上六点时,当地时间可能还处于凌晨 3 点,天空一片漆黑。

而美国同样横跨多个时区,但是美国本土使用了西部时间(-8)、山地时间(-7)、中部时间(-6)、东部时间(-5),共四个时区(阿拉斯加和夏威夷群岛分别是 -8 和 -10 )。所以简单的说美国时区就是 -8 区,这是不正确的。

国际日期变更线

东 12 区和西 12 区的中央经线其实都是180°经线,为了避免同一个时区即存在新的一天,又存在旧的一天,人为规定 180° 以西至 0 点所在经线,为新的一天,以东为 旧 的一天。

但是太平洋上存在一些国家,行政区划横跨180°经线,为了方便管理,国际日期变更线其实不是一条直线。

时区介绍

前面提到,理论时区 只包括西 12 区~东 12 区 24 个时区。但是太平洋国家萨摩亚在2011年12月29日完结时把标准时间从国际日期变更线以东调整到国际日期变更线以西,即从时区 UTC-11 改为 UTC+13(夏时制由 UTC-10 改为UTC+14 )。因此,现行国际时区标准中,存在一个“东13区”。

常见的时间标准

一般说到时区,就会提到这几个名词,UTCGMTDSTCST,那这几个名词分别代表什么含义呢?

GMT

GMT 即 Greenwich Mean Time, 代表格林威治标准时间

前文提到,1884 年国际经度会议决定选择格林威治的子午线,作为划分地球东西两半球的经度零度。而格林威治皇家天文台早在十七世纪,就已经是海上霸主大英帝国的扩张而进行天体观测。

对全球而言,这里所设定的时间是世界时间参考点,全球都以格林威治的时间作为标准来设定时间。

常说的时间戳 — timestamp,就是指格林威治时间 1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总秒数。

UTC

UTC 即 Coordinated Universal Time ,代表世界协调时间协调世界时

UTC 是经过平均太阳时(以格林威治时间 GMT 为准)、地轴运动修正后的新时标以及以“秒”为单位的国际原子时所综合精算而成的时间,计算过程相当严谨精密。协调世界时 是最接近 GMT 的几个替代时间系统之一。

普遍认为,UTC 时间被认为能与 GMT 时间互换,但 GMT 时间已不再被科学界所确定。

一般来说,当我们提到 UTC 时间而不带任何别的修饰时,常指 UTC 0点。

UTC 和 GMT 唯一的差别,UTC 有闰秒,GMT 没有

    // UTC 格林威治时间 2023-01-29T09:08:18.927058Z
    println(Instant.now())
    // UTC 格林威治时间 2023-01-29T09:08:18.941339Z
    println(Instant.now().atOffset(ZoneOffset.UTC))
    // UTC 北京时间    2023-01-29T17:08:18.942359+08:00[Asia/Shanghai]
    println(Instant.now().atZone(ZoneId.of("Asia/Shanghai")))
    // UTC 北京时间    2023-01-29T17:08:18.979096
    println(LocalDateTime.now())

DST

DST 即 Daylight Saving Time ,代表 日光节约时间 。这是一个完全由各国政府主导的行政行为,即与 GMT、UTC 这两种基于地理的时间标准而言,DST 不是一种参考经线坐标的标准。

所谓日光节约时间,是指在夏天太阳升起的比较早时,将时钟拨快一小时,以提早日光的使用,削减灯光照明和耗电开支。在英国则称为夏令时间(Summer Time)。

全球仍有部分国家在实施夏令时。值得注意的是,我国在1986年至1991年期间也使用了夏令时,可以参考 百度百科-夏令时 中对中国政策部分的描述。

简而言之,我们国家在上述时期的夏天, 打印出来的时区是 +9 区

    // 北京标准时间    1985-07-01T00:00+08:00[Asia/Shanghai]
    println(LocalDateTime.of(1985, 7, 1, 0, 0, 0).atZone(ZoneId.of("Asia/Shanghai")))
    // 北京夏令时间    1986-07-01T00:00+09:00[Asia/Shanghai]
    println(LocalDateTime.of(1986, 7, 1, 0, 0, 0).atZone(ZoneId.of("Asia/Shanghai")))
    // 北京标准时间 1992-07-01T00:00+08:00[Asia/Shanghai]
    println(LocalDateTime.of(1992, 7, 1, 0, 0, 0).atZone(ZoneId.of("Asia/Shanghai")))

各国标准

每个国家/地区使用的时区标准,都用不同的简称,可参考 moment.timezone.。java.time.ZoneId 维护了一份国际时区标准中的地区名称:

    public static final Map<String, String> SHORT_IDS = Map.ofEntries(
        entry("ACT", "Australia/Darwin"),
        entry("AET", "Australia/Sydney"),
        entry("AGT", "America/Argentina/Buenos_Aires"),
        entry("ART", "Africa/Cairo"),
        entry("AST", "America/Anchorage"),
        entry("BET", "America/Sao_Paulo"),
        entry("BST", "Asia/Dhaka"),
        entry("CAT", "Africa/Harare"),
        entry("CNT", "America/St_Johns"),
        entry("CST", "America/Chicago"),
        entry("CTT", "Asia/Shanghai"),
        entry("EAT", "Africa/Addis_Ababa"),
        entry("ECT", "Europe/Paris"),
        entry("IET", "America/Indiana/Indianapolis"),
        entry("IST", "Asia/Kolkata"),
        entry("JST", "Asia/Tokyo"),
        entry("MIT", "Pacific/Apia"),
        entry("NET", "Asia/Yerevan"),
        entry("NST", "Pacific/Auckland"),
        entry("PLT", "Asia/Karachi"),
        entry("PNT", "America/Phoenix"),
        entry("PRT", "America/Puerto_Rico"),
        entry("PST", "America/Los_Angeles"),
        entry("SST", "Pacific/Guadalcanal"),
        entry("VST", "Asia/Ho_Chi_Minh"),
        entry("EST", "-05:00"),
        entry("MST", "-07:00"),
        entry("HST", "-10:00")
    );

参考资料:

  1. 时区与JS中的Date对象
  2. java-8-date-localdate-localdatetime-instant