本文作者王明是360导航前端团队前端开发工程师
原文标题:JS历史最头疼的对象Date即将淘汰,替代物Temporal真的好用(全网首发Temporal教程)
Date背景
日期处理javajava.Util.DateJava
Date存在的问题
不支持除用户本地时间以外的时区
时区信息
解析器行为不可靠以至于无法使用
new Date();
new Date(value);
new Date(dateString);
new Date(year, monthIndex [, day [, hours [, minutes [, seconds [, milliseconds]]]]]);
输入的参数格式问题('2022-02-22')(2022,02,22)
计算 API 缺失
比较两个时间的长短时间之间的加减运算
不支持非公历
公历农历
Temporal的诞生
DateDateDateTemporal
TemporalTemporal
$ npm install @js-temporal/polyfill
import { Temporal} from '@js-temporal/polyfill';
TemporalMathPromise
Temporal
ISO 8601日期和时间
时区
日历
ISO 8601格式
对比 Date
new Date()
//Fri Jan 28 2022 17:03:11 GMT+0800 (中国标准时间)
Date时区和历法
Temporal各种类型介绍
Temporal类型转换
功能关系Temporal
TemporalTemporal
ZonedDateTime
Temporal特定区域特定时刻
北京时间2008年5月12日14时28分4秒纽约时间2008年5月12日01时28分4秒
如何获得一个 ZonedDateTime 类型?
Temporalnew 构造函数()from方法
new 构造函数()方式
参数:(纳秒数,时区,日历),不同类型要求的参数不同。
Unix 纪元
Temporal
new Temporal.ZonedDateTime(0n, 'Asia/Shanghai', 'chinese');
//Temporal.ZonedDateTime <1970-01-01T08:00:00+08:00[Asia/Shanghai][u-ca=chinese]>
TemporaltoString()Object.prototype.toString()Temporal
toString()
new Temporal.ZonedDateTime(0n, 'Asia/Shanghai', 'chinese').toString();
//1970-01-01T08:00:00+08:00[Asia/Shanghai][u-ca=chinese]
1970-01-01T08:00:00+08:001970-01-01T00:00:00+00:00
Temporal
溢出处理Temporal
接受字符串
Temporal.ZonedDateTime.from('2022-02-28T00:00:00+08:00[Asia/Shanghai]').toString();
//2022-02-28T00:00:00+08:00[Asia/Shanghai]
or
接受对象,({时区,日期,日历},options)
容错机制日期溢出{ overflow: 'constrain' }{ overflow: 'reject' }
constrain溢出处理
//输入 31 天,得到 28 天
Temporal.ZonedDateTime.from({ timeZone: 'Asia/Shanghai', year: 2022, month: 2, day: 31}, { overflow: 'constrain' }).toString();
//2022-02-28T00:00:00+08:00[Asia/Shanghai]
reject
Temporal.ZonedDateTime.from({ timeZone: 'Asia/Shanghai', year: 2022, month: 2, day: 31}, { overflow: 'reject' }).toString();
//RangeError: value out of range: 1 <= 31 <= 28
Instant
定义:负责单个时间点(称为 “精确时间” ),精度以纳秒为单位。不存在时区和日历信息。
2020-01-23T17:04:36.491865121-08:00瞬间
Instant
new Temporal.Instant( bigint )
Unix 纪元
new Temporal.Instant(1553906700000000000n);
//2019-03-30T00:45:00Z
new Temporal.Instant(0n);
//1970-01-01T00:00:00Z
new Temporal.Instant(-2208988800000000000n);
//1900-01-01T00:00:00Z
ISO 8601
Temporal.Instant.from(thing: any)
Instant
Temporal.Instant.from('2019-03-30T01:45:00+01:00[Europe/Berlin]');
Temporal.Instant.from('2019-03-30T01:45+01:00');
Temporal.Instant.from('2019-03-30T00:45Z');
虽然前两个携带了时区信息,但获取到的Instant 时间值相同,三个都是 2019-03-30T00:45Z
Plain XX系列
Temporal
农历下午2:00
InstantInstantPlain XX
PlainDateTimePlaindatePlaintimePlainYearMonthPlainMonthDay
PlainDateTime
PlainDateTime
new Temporal.PlainDateTime(year,month,day...)
年 -> 纳秒
new Temporal.PlainDateTime(2020, 3, 14, 13, 37)
//2020-03-14T13:37:00
Temporal.PlainDateTime.from()
Temporal.PlainDateTime.from({ year: 2001, month: 1, day: 1, hour: 25 ,calendar:'chinese'}, { overflow: 'constrain' }).toString()
//2001-01-24T23:00:00[u-ca=chinese]
TimeZone
Temporal
东八区
TimeZone
new Temporal.TimeZone(string)
string:对一个时区的描述
//东八区,即北京时间
new Temporal.TimeZone('8:00');
//直接字符串描述,前提是 Temporal 内部有定义
new Temporal.TimeZone('Asia/Shanghai');
//Asia/Shanghai
from同理
Temporal.TimeZone.from('Asia/Shanghai');
//Asia/Shanghai
在和其他类型搭配时,可以直接使用字符串(“Asia/Shanghai”),或者 Temporal.TimeZone对象
例子:
ZonedDateTimeTemporal.TimeZone
new Temporal.ZonedDateTime(0n, Temporal.TimeZone.from('Asia/Shanghai'));
//1970-01-01T08:00:00+08:00[Asia/Shanghai]
等价于
new Temporal.ZonedDateTime(0n, 'Asia/Shanghai'));
Calendar
Temporal
农历
Calendar
TimeZone
new Temporal.Calendar('chinese').toString();
//chinese
Temporal.Calendar.from('chinese').toString();
//chinese
Calendar日历属性
日历属性plainXX系列ZonedDateTime
withCalendar
例子:
plainXX系列 添加日历属性
没有添加日历属性前
Temporal.PlainDate.from('2019-02-06');
//2019-02-06
添加日历属性后
Temporal.PlainDate.from('2019-02-06').withCalendar('chinese');
//2019-02-06[u-ca=chinese]
ZonedDateTime 添加日历属性
没有添加日历属性前
Temporal.ZonedDateTime.from('2022-02-28T00:00:00+08:00[Asia/Shanghai]')
//2022-02-28T00:00:00+08:00[Asia/Shanghai]
添加日历属性后
Temporal.ZonedDateTime.from('2022-02-28T00:00:00+08:00[Asia/Shanghai]').withCalendar('chinese')
//2022-02-28T00:00:00+08:00[Asia/Shanghai][u-ca=chinese]
Duration
算术
一小时一分钟一小时十分钟Duration
DurationDateISO 8601
ISO 8601PT
DurationPT
举例:
P1YPT
PT1MPT
Duration
Duration
new Temporal.Duration()
undefined0
new Temporal.Duration(1, 2, 3, 4, 5, 6, 7, 987, 654, 321);
// P1Y2M3W4DT5H6M7.987654321S
//中文翻译 => 1年2月3周4天5小时6分钟7秒987毫秒654微秒321纳秒
new Temporal.Duration(0, 0, 0, 40);
// P40D 中文翻译 => 40天
Temporal.Duration.from(undefined, undefined, undefined, 40);
// P40D
new Temporal.Duration();
// PT0S
DurationDuration日期与时间
日期或时间
Durationcompare
one = Temporal.Duration.from({ hours: 79, minutes: 10 });//PT1H10M
two = Temporal.Duration.from({ days: 3, hours: 7, seconds: 630 });//P3DT7H630S
Temporal.Duration.compare(one,two)
//-1
onetwo
onetwo
onetwo
TimezoneCalendar算术
PlainDateTime
one = Temporal.PlainDateTime.from('1995-12-07T03:24');
two = Temporal.PlainDateTime.from('1995-12-07T01:24');
Temporal.PlainDateTime.compare(two,two)
//1
日期或时间
加法:
Temporal.Duration.from('PT1H'); //PT1H
hour.add({ minutes: 30 });
// => PT1H30M
减法:
hourAndAHalf = Temporal.Duration.from('PT1H30M'); //PT1H30M
hourAndAHalf.subtract({ hours: 1 }); // => PT30M
TimezoneCalendar
PlainDateTime
dt = Temporal.PlainDateTime.from('1995-12-07T03:24:30.000003500');
dt.add({ years: 20, months: 4, nanoseconds: 500 });
// => 2016-04-07T03:24:30.000004
Temporal类型之间的转换
类型转换
通道桥梁
Instant => ZonedTimeDate
转换前
Temporal.Instant.from('2020-08-05T20:06:13+0900').toString()
//2020-08-05T11:06:13Z
转换后
Temporal.Instant.from('2020-08-05T20:06:13+0900').toZonedDateTimeISO('Asia/Tokyo').toString();
//2020-08-05T20:06:13+09:00[Asia/Tokyo]
ZonedTimeDate => Instant
转换前
Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]').toString();
//2020-11-01T01:45:00-07:00[America/Los_Angeles]
转换后
Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]').toInstant().toString();
//2020-11-01T08:45:00Z
ZonedTimeDate => PlainDateTime
转换前
Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]').toString()
//2020-11-01T01:45:00-07:00[America/Los_Angeles]
转换后
Temporal.ZonedDateTime.from('2020-11-01T01:45-07:00[America/Los_Angeles]').toPlainDateTime().toString();
//2020-11-01T01:45:00
PlainDateTime => ZonedTimeDate
转换前
Temporal.PlainDateTime.from('2020-08-05T20:06:13').toString()
//2020-08-05T20:06:13
转换后
Temporal.PlainDateTime.from('2020-08-05T20:06:13').toZonedDateTime('Asia/Tokyo').toString();
//2020-08-05T20:06:13+09:00[Asia/Tokyo]
总结
Date
TemparalTimeZone
算术运算
CalendarTemparal
Temporalnew 构造函数()FromFrom日期溢出
Temparal功能Temparal
参考资料
[1]
博客: https://tc39.es/proposal-temporal/docs/
- END -
关于奇舞团
奇舞团是 360 集团最大的大前端团队,代表集团参与 W3C 和 ECMA 会员(TC39)工作。奇舞团非常重视人才培养,有工程师、讲师、翻译官、业务接口人、团队 Leader 等多种发展方向供员工选择,并辅以提供相应的技术力、专业力、通用力、领导力等培训课程。奇舞团以开放和求贤的心态欢迎各种优秀人才关注和加入奇舞团。