Time Zone, Leap Year, Date Format, Epoch Time 时区, 闰年, 日期格式

前言

 以前有写过一篇了, 但很乱, 这篇就作为它的整理版吧. 

 

Leap Year 闰年

闰年是指那些有 366 天, 二月份有 29号 的年份. 比如 2020年 有 2月29日, 所以 2020 就是闰年.

why leap year?

地球自转一圈是一天, 地球绕太阳转一圈是一年. 地球绕太阳转一圈的同时, 地球一共自转了 365 圈, 所以就是 365 天.

这个计算并不精准, 因为地球并不是刚刚好转 365 圈的, 其实是超过的. 正确的天数是 365天5小时48分46秒

于是, 如果按 365 天计, 每一年就少了 5 小时多. 每四年就少了一天. 久了就越差越远了.

所以必须弥补回来, 最简单的方式是, 每四年补回一天. 这样就准了

四年一闰, 百年不闰, 四百年再闰

但仔细计算会发现, 每四年加一天是有多的. 久而久之也会不精准, 于是最终就变成了大家熟悉的四年一闰, 百年不闰, 四百年再闰.

console.log(new Date('1900-02-29').toLocaleDateString('en-MY')); // 01/03/1900 没有 因为百年不闰
console.log(new Date('1904-02-29').toLocaleDateString('en-MY')); // 29/02/1904 有,  因为四年一润
console.log(new Date('1908-02-29').toLocaleDateString('en-MY')); // 29/02/1908 有,  因为四年一润
console.log(new Date('2000-02-29').toLocaleDateString('en-MY')); // 29/02/2000 有,  因为四百年再润

每四年调一次, 100 年又调一次, 400 年又调一次. 所以时间一直都是有微差的 (但很小很小), 直到 400 年才对准.

 

 

Time Zone 时区

世界各地的时间很奇妙, 比如跨年都是在 12月31号 晚上 11:59分 放烟花庆祝. 但是美国的晚上是马来西亚的白天 (因为彼此在地球的另一端, 一个面向太阳, 另一个就是夜晚)

如果用统一时间的话, 会有两个后果, 第一, 马来西亚人只能在白天放烟花庆祝新年, 第二, 马来西亚人必须在 12月31号 下午 3:59分 倒数跨年. 显然这两个都不可能被接受. 所以不同的地区必须要有不同的时间 (时区).

但统一时间任然是有必要的, 不然跨国沟通也会有问题, 所以除了时区, 我们也有统一的时间 UTC/GMT (它以英国时区为标准, 为什么是英国呢? 因为这个标准是在大英帝国时代定下的)

例子:

马来西亚的时区是 Malaysia Standard Time 它的 offset 是 +08.00 对应英国的 UTC +00:00 快了 8 小时. 也就是说马来西亚活在未来 8 小时.

时区是国家规定的, 而且是可以改的...

马来西亚的时区以前是 +07:30 后来换成了 +08:00. 这种修改很容易引起 Bug. 因为我们普遍会认为 offset = timezone.

但其实 timezone 指的是一个规则. 里面可能包含了许多不同的 offset. 

const time1 = new Date(1981, 1, 1);
console.log(time1.toUTCString()); // Sat, 31 Jan 1981 16:30:00 GMT
console.log(time1.getTimezoneOffset()); // -450 
const time2 = new Date(1982, 1, 1);
console.log(time2.toUTCString()); // Sun, 31 Jan 1982 16:00:00 GMT
console.log(time2.getTimezoneOffset()); // -480 多了 30 minutes

JS 的 Date 包含了 timezone 里所有不同年份的历史 offset 哦.

时区小知识:

整个地球分为 24 个时区, 从 -12:00 到 +13:00

UTC (Universal Time Coordinated) 全球统一时间 +00:00, 也是英国伦敦的时间

GMT(Greenwich Mean Time) UTC 的前生, 现在都叫 UTC 了.

PST (Pacific Standard Time -08:00) 也是很常见的时区. 美国, 加拿大那一带用的

DST ( Daylight Saving Time 夏令时)  夏令时是一个机制, 为了节约能源, 它的做法是在夏季左右把时间调后一小时, 然后又在夏季结束后调前一小时, 这个规则也是通过时区管理的.

例子: "Sun Mar 09 2014 01:59:00 GMT-0500 (EST)" -> "Sun Mar 09 2014 03:00:00 GMT-0400 (EDT)". 两点钟消失了, 因为时间被调后了一小时, offset 从 -0500 变成了 -0400.

 

日期格式

不同国家除了时区不一样, 日期的格式也有很多区别.

new Date().toLocaleString('en-US'); // 1/15/2023, 2:13:33 PM
new Date().toLocaleString('zh-TW'); // 2023/1/15 下午2:13:33
new Date().toLocaleString('ms-MY'); // 15/1/2023, 2:13:33 PTG

美国的格式是 1/15/2023 月/日/年, pm 代表晚上

台湾是 2023/1/15 年/月/日

马来西亚是 15/1/2023 日/月/年 PTG 是 petang 马来语, 下午的意思

这些格式最烦人的就是日和月经常会分不清.

程序员比较喜欢和常看见的格式是

new Date().toISOString(); // 2023-01-15T06:19:08.034Z
new Date().toUTCString(); // Sun, 15 Jan 2023 06:19:08 GMT

ISO : 年-月-日 z 表示时区是 UTC

UTC/GMT 用了 Jan 来表示月份, 这样就不容易和日搞混了.

注:语言和格式 (排位顺序),都会收地域的影响。

字符

参考: C# DateTime Format

日期格式可以用一些字符来表达 (不同语言可能有微差, 但基本规则是一致的)

比如 C# 的 yyyy-MMM-dd hh:mm:ss tt 表示 年-月-日 时:分:秒: am/pm

规则有三个特点

1. 缩写, y 是 year 的缩写, s 是 second 的缩写

2. 大小写, month 和 minutes 的缩写都是 m, 所以需要靠大小写来区分, M 代表 month, m 代表 minute.

3. 数量 d 表示最少显示一位数, dd 表示最少两位数. 比如一号, d=1, dd=01, 11号则是一样的 d=11, dd=11

常用:

yy = 23

yyyy = 2023

M = 1, 11

MM = 01, 11

MMM = Jan, Nov (文字)

MMMM = January, November

d = 1, 11

dd = 01, 11

ddd = Mon (星期几)

dddd = Monday

H = 1, 13 (24小时制)

HH = 01, 13

h = 1, 1

hh = 01, 01

m = 1

mm = 01

s = 1

ss = 01

tt = AM/PM (其它语言可能不一样)

K = +08:00 (其它语言可能不一样)

 

Epoch Time

0001 年是耶稣诞生的年份, 1970 年是 Unix 诞生的年份.

Epoch Time 指的就是 1970年1月1 号. JavaScript Date.getTime 返回的就是 1970年1月1号到指定 datetime 的毫秒数.

 

posted @ 2023-01-15 00:31  兴杰  阅读(301)  评论(0编辑  收藏  举报