- 时间字符串: 指的是 YYYY-MM-DD 、 HH:mm:ss诸如,在本地显示的时间字符串
理解时间和时区
A
假设张三在A地区(+8)执行了一行代码,new Date('2022-01-01 00:00:00:000').valueOf(),同时老王在B地区(+7)地区也执行了这行代码,请问他们获得的时间戳是否相同?
答: 不相同。为什么呢,因为A地区 22年一月一号0点的时候,B地区比我们早了一个钟, 时钟上显示着 '2021-12-31 23:00:00',而当B地区到了22年一月一日0点的时候,我们已经过了一个钟时钟上显示的是 '2022-01-01 01:00:00'
// A地区 +8
new Date('2022-01-01 00:00:00:000').valueOf() // 1640966400000
// B地区 +7
new Date('2022-01-01 00:00:00:000').valueOf() // 1640970000000
B
假设张三在A地区(+8)执行了一行代码,new Date(1640966400000),同时老王在B地区(+7)地区也执行了这行代码,请问他们获得的时间戳是否相同?
答: 不相同。这个原因和上面是一样的,同一个时刻,不同的地区上,时钟显示的是不一样的,ID比我们早了一个时区,自然是比我们快了一个钟。
// A +8
new Date(1640966400000) // Sat Jan 01 2022 00:00:00 GMT+0800 (A地区标准时间)
// B +7
new Date(1640966400000) // Fri Dec 31 2021 23:00:00 GMT+0700 (B地区标准时间)
从这两个例子我们可以看到,
- 当时间字符串相同时,在不同的地区获得的时间戳是不同的
- 当时间戳相同时,在不同的地区获取的时间字符串是不同的
看到这里,你似乎已经对时间、时区、时间字符串有了一个初步的印象和理解。
关于时间和时区
-
时间是什么?
这是个很深刻的问题了,关于时间的定义,很复杂。但是简单来说,指的是某一瞬间。
-
时间戳、UTC、GMT这些都是什么?
-
时间戳需要理解时区概念吗?
时间戳是不需要考虑时区概念的。
为什么这样说,假设 1657535893504(东八区 2022-07-11 18:39:22) 这个时间戳,无论在哪个国家哪个地区,它都代表着某一个时刻时间,它是时间本身的记录。
-
那时间字符串有时区概念呢?
当然有,因为在不同的时区下,同一个时间字符串代表的是不同的时间本身。 时间字符串只是当地时间的一个表达。
-
时间字符串和 UTC 、 GMT有什么区别,不都是字符串吗?
Good,福尔摩斯的你已经发现了端倪。 '2022-01-01 00:00:00' 和 'Sat Jan 01 2022 00:00:00 GMT+0800 (中国标准时间)' 虽然同样都是字符串,但是前者没有时区,所以在不同的时区下,它代表着不同的时间,后者带上了时区,它永久地指向了一个特定的时间。
-
理解dayjs对象?
我们应该知道dayjs对象本质上就是时间,在理解 时区、本地字符串、时间的关系和转换时,我们需要把dayjs对象当成时间当成时间戳去处理。
Dayjs的使用
从上面我们知道, 时间字符串 + 时区 = 时间。 那我们再来了解一下dayjs的api
-
dayjs()
这是最基础的一个api。调用时,时区都是机器时区,无论你是否设置了tz的默认时区。
从下面可以看到,当我们传入一个普通的时间字符串时,它是指我们本地的2022-01-01
-
dayjs().tz() // tz(timezone?: string, keepLocalTime?: boolean): Dayjs
interface Dayjs { tz(timezone?: string, keepLocalTime?: boolean): Dayjs }可以注意到,此时的tz是dayjs实例上的共有函数,它的作用是转换时区。记住我们上面的等式, 时间字符串 + 时区 = 时间。所以,时区改变了,要么时间字符串改变,要么时间改变,这里是通过第二个参数去控制的,不传第二个函数默认是false。
- keepLocalTime为false, 时间不变,时间字符串改变了
- keepLocalTime 为 true , 时间字符串没变,时间变了
- keepLocalTime为false, 时间不变,时间字符串改变了
-
dayjs.tz()
可以先看下它的类型定义
interface DayjsTimezone { (date: ConfigType, timezone?: string): Dayjs (date: ConfigType, format: string, timezone?: string): Dayjs } const tz: DayjsTimezone首先和第二个函数不同,它是挂载在dayjs上的静态函数,它的作用和第一个函数 dayjs() 类似,都是用来构造dayjs对象的,但是不同的是,你可以指定你的目标时区,如果第二个参数没传,会使用tz.setDefault指定的时区
仍然是那个等式, 时间字符串 + 时区 = 时间,所以如果第一个参数传入了时间字符串,那么就是 时间字符串 + 指定时区, 如果传入的是时间,则format的时候是结果会不同
-
传入时间字符串
-
传入时间
-
传入dayjs
在上面我们说过,dayjs对象需要当成时间来理解,所以传入dayjs 等同于 传入时间。那么当我们需要保持时间字符串不变时,那我们就需要先format一下。
可能有的同学已经发现了,既然传入的是dayjs,为啥不直接调用第二个例子, tz这个实例方法呢? 这里有两个理由:
-
如果是时间选择器出来的时间,这个dayjs可能是没有tz这个实例方法的,因为没有继承过timezone
dayjs.extend(utc) dayjs.extend(timezone) -
通常来说,都是用dayjs.tz.setDefault 设置一个默认的目标时区,而tz这个实例方法,又不能绕开第一个参数去设置第二个参数
-
-