万字长文:JSDate已死,2025年TemporalAPI永生?

前有科技后进阶 2025-03-21 13:35:04

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

图片来自:https://refine.dev/blog/temporal-date-api/

随着 Deno 高调宣布支持 Temporal API,于是迫不及待的在 Chrome 浏览器中尝试了一番发现,即使最新版本的 Chrome v120 依然没有支持 Temporal API。而且根据 caniuse 的数据,目前几乎没有主流浏览器开始支持该 API。

摆着一副对新知识的好奇,我决定还是对 Temporal API 一探究竟,万一哪天遇到面试题也能多少有点了解。话不多说,直接进入正题!

1.JavaScript Date 对象的难题

由于历史原因,JS 语言的 Data 对象完全复制了 Java 中的 Data 类,Data API 存在一些问题,比如:对象不是 immutable、仅支持 UTC 和本地时区、从字符串中解析日期的不可靠、不支持公历以外的其他历法等等。

1.1 Date 对象是可变的

比如下面的例子:

var date = new Date("2023-07-16");// 原始 Date 对象console.log(date);//2023-07-16T00:00:00.000Zdate.setDate(date.getDate() + 1);// change the date - add 1 dayconsole.log(date);// 2023-07-17T00:00:00.000Z the original date has been changed

上面的示例代码使用 new Date() 命令来初始化一个新的日期对象,然而该对象是可变的,为了获得更新的值则必须改变原始对象,比如:setDate() 函数操作。

因此,当使用 JavaScript 的内置 Date 功能时,则必须小心如何使用和修改日期对象。 如果过多地修改原始日期对象,很可能会陷入意想不到的结果之中。

immutable 概念最近在前端非常火热,因为其可以生成更健壮、更易于维护的代码。比如当开发者对 DayJS (Moment.js 不建议使用,官方已停止维护)对象执行操作(如:添加或减去时间)时,该库将返回具有修改值的新实例,而原始实例保持不变,从而防止数据发生意外更改,并降低引入难以追踪的错误的风险。

var originalDate = dayjs("2023-07-16");var modifiedDate = originalDate.add(1, "day");console.log(originalDate.format("YYYY-MM-DD")); // 输出: "2023-07-16"console.log(modifiedDate.format("YYYY-MM-DD")); // 输出: "2023-07-17"1.2 仅支持 UTC 和本地时区(Local Time Zone)和 ISO-8601GMT 和 UTC

为了区分这个概念,需要对 GMT 和 UTC 进行简单说明:

GMT(Greenwich Mean Time) :格林尼治标准时间,格林尼治是地球本初子午线的标界处,太阳每天经过格林尼治正上方的时间就是中午 12 点。由于地球在椭圆轨道运行不均匀和太阳时存在偏差,同时自转不规则和变慢,导致 GMT 越来越不准确。UTC(Coordinated Universal Time):表示协调世界时,使用原子钟来计时,是世界上调节时钟和时间的主要标准,与 0 度经线的平太阳时相差不超过 1 秒,且不遵守夏令时。UTC 是最接近 GMT 的几个替代时间之一。对于大多数用途来说,UTC 被认为能与 GMT 时间互换,但 GMT 时间已不再被科学界所确定,目前基本以 UTC 时间作为标准UNIX(Uniplexed Information and Computering System)时间:是类 UNIX 系统上使用的时间表示方式,使用 UTC 时 1970 年 1 月 1 日 0 时 0 分 0 秒起到现在的总秒数本地时区(Local Time Zone)

除了 GMT 和 UTC 外,本地时区也是深入 Date 对象的基础。

DST(Daylight Saving Time):夏令时,是一种为节约能源而人为规定地方时间的制度,在这一制度实行期间所采用的统一时间称为 “夏令时间”。一般在天亮早的夏季人为将时间调快一小时,可以使人早起早睡,减少照明量,以充分利用光照资源,从而节约照明用电,各个采纳夏时制的国家具体规定不同。全世界有近 110 个国家每年要实行夏令时,比如中国使用 Asia/Shanghai 和 Asia/Urumqi 两个时区TZ(Time Zone) database :是一个全球时区信息的仓库,由 IANA(Internet Assigned Numbers Authority) 维护,记录了一组世界各地时间历史的代码和数据。包括时区 ID,对应的 UTC 偏移量,夏令时相关信息。日期格式 ISO-8601

当日期用数字表示时,可以用不同的方式解释。 例如,01/05/22 可能是 2022 年 1 月 5 日或 2022 年 5 月 1 日。在个人层面上,这种不确定性非常无语,在商业环境中有时候可能会非常重要。 当日期不明确时,组织会议和交付、签订合同和购买机票可能会非常困难。

ISO 8601 通过制定国际商定的日期表示方式来解决这种不确定性:

YYYY-MM-DD

因此,ISO 8601 中用于表示日期和时间的元素顺序如下:年、月、日、时、分、秒、毫秒。例如,2022 年 9 月 27 日下午 6 点 表示为 2022-09-27 18:00:00.000。

1.3 从字符串中解析日期的不可靠

Javascript 实际上并不支持 Date, JavaScript 仅支持日期时间。 所有 Javascript 日期都是 Unix 时间戳。 这意味着如果尝试创建一个 Date,实际上是在创建一个日期时间,所有未指定时间的 Javascript 日期默认为当天的午夜。

let date = new Date(2011, 1, 22);// 请注意,生成日期附有时间:// Tue Feb 22 2011 00:00:00 GMT+0000 (Greenwich Mean Time)

如果开发者知道月份从 0 开始,那么按照上面的方法解析日期没啥问题,但解析日期字符串在不同浏览器中会有很大差异,强烈建议不要解析日期字符串。 在 ECMAScript 5 规范之前,从未定义过 Date 如何解析字符串日期,并且不同的浏览器有许多历史怪癖,使其非常不可靠。

根据当前规范,只有符合 ISO-8601 标准的字符串才能被 Javascript 解析,任何其他日期都应返回 NaN,即:

let parseMyDate = Date.parse('2022-03-21T11:00:01+00:00');// 不能解析则返回NaN

然而,事实并非如此, 许多浏览器允许用另外的格式进行日期解析,这就是可能会令人困惑的地方。 假设想要解析标准 dd/mm/yyyy 日期格式的日期格式,则获取一个标准日期,并将其传递给 parse() 函数:

let myDate = new Date("5/1/2020");console.log(myDate);

在所有现代浏览器中,其使用 US 日期格式,即 mm/dd/yyyy , 这意味着其返回 5 月 1 日,而不是 1 月 5 日,从而导致意外结果。

1.4 不支持公历以外的其他历法

公历(Gregorian calendar)是一种确定日期的系统,由教皇格列高利十三世(Pope Gregory XIII )于公元 1582 年引入,其基于地球绕太阳的运动(这意味着它是太阳历)并包括闰年。

闰年是指在日历中添加额外的一天以帮助提高时间准确性的一年,此日历有时被称为 “新式” 日历,与 “旧式” 儒略历不同 。

虽然世界上大多数地区都使用公历,但依然存在区域日历(Regional Calendar Eras)。 calendar 属性的值是在构造时设置的,可以通过区域设置标识符的 ca 键,也可以通过 Intl.Locale() 构造函数的日历选项。 如果两者都存在,则后者优先; 如果两者都不存在,则该属性的值未定义。

比如下面的示例:

const locale = new Intl.Locale("fr-FR-u-ca-buddhist");console.log(locale.calendar); // Prints "buddhist"const locale = new Intl.Locale("fr-FR", { calendar: "buddhist"});console.log(locale.calendar); // "buddhist"2. Temporal 的横空出世2.1 Temporal 解决了 Date 的什么问题

文章以上章节重点讲述了 JavaScript 中 Date 的诸多限制,基于这些限制诞生了 Temporal 提案,Temporal 是一个充当顶级命名空间(如: Math)的全局对象,为 ECMAScript 语言带来了更加现代的日期 / 时间 API。

Temporal 解决了以上 Date 的诸多问题:

提供易于使用的 API 用于日期和时间计算对所有时区的一流支持,包括: DST(Daylight saving time) 安全的计算仅处理表示固定日期和时间的对象解析严格指定的字符串格式支持非公历

Temporal 为仅日期、仅时间和其他范围用例提供单独的 ECMAScript 类,从而使代码更具可读性,进而防止实际未知值的错误值假设,比如:0、UTC 、本地时区等。

在浏览器中打印 Temporal 对象,可以看到下面的输出示例:

2.2 Temporal 常见 API

Temporal API 遵循的约定是,对于没有关联时区的对象使用名称以 “Plain” 开头的类型(例如: Temporal.PlainDate、Temporal.PlainTime 和 Temporal.PlainDateTime)。

由于时区和夏令时的原因,此类类型和精确时间类型(Temporal.Instant 和 Temporal.ZonedDateTime)之间的转换可能会不明确,而 Temporal API 允许开发人员配置如何解决这种不明确性。

// 通过提供时区将各种本地时间类型转换为精确时间类型date = Temporal.PlainDate.from('2019-12-17');// 如果省略时间,则当地时间默认为当天的开始时间zdt = date.toZonedDateTime('Asia/Tokyo'); // => 2019-12-17T00:00:00+09:00[Asia/Tokyo]zdt = date.toZonedDateTime({timeZone: 'Asia/Tokyo', plainTime: '10:00'}); // => 2019-12-17T10:00:00+09:00[Asia/Tokyo]time = Temporal.PlainTime.from('14:35');zdt = time.toZonedDateTime({timeZone: 'Asia/Tokyo', plainDate: Temporal.PlainDate.from('2020-08-27') }); // => 2020-08-27T14:35:00+09:00[Asia/Tokyo]dateTime = Temporal.PlainDateTime.from('2019-12-17T07:48');zdt = dateTime.toZonedDateTime('Asia/Tokyo'); // => 2019-12-17T07:48:00+09:00[Asia/Tokyo]// 获取自 UNIX 纪元以来的准确时间(以秒、毫秒或纳秒为单位)。inst = zdt.toInstant();epochNano = inst.epochNanoseconds; // => 1576536480000000000nepochMilli = inst.epochMilliseconds; // => 1576536480000epochSecs = inst.epochSeconds; // => 1576536480Temporal.NowTemporal.Now.instant() - 获取当前系统的准确时间Temporal.Now.timeZoneId() - 获取当前系统时区,比如在杭州则输出'Asia/Shanghai'Temporal.Now.zonedDateTime(calendar) - 获取系统时区和指定日历中的当前日期和挂钟时间Temporal.Now.zonedDateTimeISO() - 获取系统时区和 ISO-8601 日历中的当前日期和挂钟时间Temporal.Now.plainDate(calendar) - 获取系统时区和指定日历中的当前日期Temporal.Now.plainDateISO() - 获取系统时区和 ISO-8601 日历中的当前日期Temporal.Now.plainTimeISO() - 获取系统时区中的当前挂钟时间和 ISO-8601 日历Temporal.Now.plainDateTime(calendar) - 获取系统时区中的当前系统日期 / 时间,但返回一个不记得其时区的对象,因此不应用于派生其他值(例如 12 小时后) 使用夏令时 (DST) 的时区。Temporal.Now.plainDateTimeISO() - 与上面相同,但返回 ISO-8601 日历中的日期时间console.log('Initialization complete', Temporal.Now.instant());// 实例化完成 2021-01-13T20:57:01.500944804ZTemporal.Instant

Temporal.Instant 表示固定时间点(称为 “exact time”),与日历或位置无关,例如 1969 年 7 月 20 日,世界标准时间 20:17。 对于人类可读的本地日历日期或时钟时间,请使用 Temporal.TimeZone 和 Temporal.Calendar 获取 Temporal.ZonedDateTime 或 Temporal.PlainDateTime。

const instant = Temporal.Instant.from('1969-07-20T20:17Z');instant.toString();// 输出 => '1969-07-20T20:17:00Z'instant.epochMilliseconds;// 输出 => -14182980000Temporal.ZonedDateTime

Temporal.ZonedDateTime 是一个时区感知、日历感知的日期 / 时间对象,它表示从地球上特定区域的角度来看在特定确切时间已经发生(或将要发生)的真实事件,例如, 美国太平洋时间 1995 年 12 月 7 日凌晨 3:24(公历)。 此类型针对需要时区的用例进行了优化,包括 DST 安全算术以及与 RFC 5545 (iCalendar) 的互操作性。

const zonedDateTime = Temporal.ZonedDateTime.from({ timeZone: 'America/Los_Angeles', // 时区 year: 1995, month: 12, day: 7, hour: 3, minute: 24, second: 30, millisecond: 0, microsecond: 3, nanosecond: 500});// 输出值 => 1995-12-07T03:24:30.0000035-08:00[America/Los_Angeles]

作为最广泛的 Temporal 类型,Temporal.ZonedDateTime 可以被视为 Temporal.TimeZone、Temporal.Instant 和 Temporal.PlainDateTime(包括 Temporal.Calendar)的组合。

Temporal.PlainDate

Temporal.PlainDate 对象表示与特定时间或时区无关的日历日期,例如 2006 年 8 月 24 日。

const date = Temporal.PlainDate.from({year: 2006, month: 8, day: 24}); // 输出 => 2006-08-24date.year; // 输出 => 2006date.inLeapYear; // 闰年输出 => falsedate.toString(); // 输出 => '2006-08-24'

也可以转换为部分日期,例如 Temporal.PlainYearMonth 和 Temporal.PlainMonthDay。

Temporal.PlainTime

Temporal.PlainTime 对象表示与特定日期或时区无关的挂钟时间,例如:晚上 7:39。

const time = Temporal.PlainTime.from({ hour: 19, minute: 39, second: 9, millisecond: 68, microsecond: 346, nanosecond: 205}); // 输出 => 19:39:09.068346205time.second; // 输出 => 9time.toString(); // 输出 => '19:39:09.068346205'Temporal.PlainDateTime

Temporal.PlainDateTime 表示不携带时区信息的日历日期和挂钟时间,例如 1995 年 12 月 7 日下午 3:00(公历)。

可以使用 Temporal.TimeZone 将其转换为 Temporal.ZonedDateTime。 对于需要时区的用例,特别是使用算术或其他派生值,可以考虑使用 Temporal.ZonedDateTime,因为该类型会自动调整夏令时。

const dateTime = Temporal.PlainDateTime.from({ year: 1995, month: 12, day: 7, hour: 15}); // 输出 => 1995-12-07T15:00:00const dateTime1 = dateTime.with({ minute: 17, second: 19}); // => 输出 1995-12-07T15:17:19Temporal.PlainYearMonth

没有日期部分的日期,这对于表达诸如 “2020 年 10 月会议” 之类的内容很有用。

const yearMonth = Temporal.PlainYearMonth.from({year: 2020, month: 10});// 输出 => 2020-10yearMonth.daysInMonth; // 输出 => 31yearMonth.daysInYear; // 输出 => 366Temporal.PlainMonthDay

不带年份部分的日期。这对于表达诸如 “Bastille Day is on the 14th of July” 之类的内容很有用。

const monthDay = Temporal.PlainMonthDay.from({month: 7, day: 14});// 输出 => 07-14const date = monthDay.toPlainDate({year: 2030});// 输出 => 2030-07-14date.dayOfWeek;// 输出 => 7Temporal.Duration

Temporal.Duration 表示时间长度,例如 5 分 30 秒。这用于日期 / 时间算术以及测量时间对象之间的差异。

const duration = Temporal.Duration.from({ hours: 130, minutes: 20});duration.total({unit: 'second'});// 输出 => 469200

与其他 Temporal 类型不同,Temporal.Duration 中的单位不会自然地环绕(Wrap Around)为 0,比如:用户可能希望持续时间为 “90 分钟”,并且不希望它意外地变成 “1 小时 30 分钟” 分钟。”

Temporal.TimeZone

Temporal.TimeZone 表示 IANA 时区、特定的 UTC 偏移量或 UTC 本身。 时区从 UTC 日期 / 时间转换为本地日期 / 时间。 因此,Temporal.TimeZone 可用于在 Temporal.Instant 和 Temporal.PlainDateTime 之间进行转换,以及找出特定 Temporal.Instant 处的偏移量。

const timeZone = Temporal.TimeZone.from('Africa/Cairo');timeZone.getInstantFor('2000-01-01T00:00');// 输出 => 1999-12-31T22:00:00ZtimeZone.getPlainDateTimeFor('2000-01-01T00:00Z'); // 输出 => 2000-01-01T02:00:00timeZone.getPreviousTransition(Temporal.Now.instant());// 输出 => 2014-09-25T21:00:00ZtimeZone.getNextTransition(Temporal.Now.instant());// 输出 => nullTemporal.Calendar

Temporal.Calendar 代表日历系统(calendar system), 大多数代码将使用 ISO 8601 日历,但也可以使用其他日历系统。

日期具有关联的 Temporal.Calendar 对象,以执行与日历相关的数学运算。 在幕后,这个数学是通过日历上的方法完成的。

const cal = Temporal.Calendar.from('iso8601');const date = cal.dateFromFields({year: 1999, month: 12, day: 31}, {});date.monthsInYear;// 输出 => 12date.daysInYear;// 输出 => 3653.Temporal 和 Date 互转

有时候需要在 Temporal 和 Date 之间互转,旧版 ECMAScript Date 转换为与精确时间中的同一时刻相对应的 Temporal.Instant 或 Temporal.ZonedDateTime 实例。

3.1 Date => Temporal.Instant 和 / 或 Temporal.ZonedDateTime

以下代码示例会将旧版 ECMAScript Date 转换为与精确时间中的同一时刻相对应的 Temporal.Instant 或 Temporal.ZonedDateTime 实例。

const legacyDate = new Date('1970-01-01T00:00:01Z');const instant = legacyDate.toTemporalInstant();// 注意:该方法当前 Date 不支持assert.equal(instant.epochMilliseconds, legacyDate.getTime());assert.equal(instant.toString(), '1970-01-01T00:00:01Z');// If you need a ZonedDateTime, use the toZonedDateTime() or// toZonedDateTimeISO() method of the resulting Instant.// You will need to specify a time zone, because legacy Date only// stores an exact time, and does not store a time zone.// When calling methods on a legacy Date instance, you must decide// whether you want that exact time interpreted as a UTC value// (using methods containing "UTC" in their names) or in the// current system time zone (using other methods). This is// confusing, so Temporal has a more explicit way to do this.// To use the system's local time zone, which corresponds to using// legacy Date's getFullYear(), getMonth(), etc. methods, pass// Temporal.Now.timeZone() as the time zone. In a browser, this// will be the user's time zone, but on a server the value may not// be what you expect, so avoid doing this in a server context.const zoned = instant.toZonedDateTimeISO(Temporal.Now.timeZoneId());assert.equal(zoned.epochMilliseconds, legacyDate.getTime());// Here's an example of using a particular time zone. Especially// in a server context, you would be getting this time zone from// elsewhere in the data that you are processing.const zoned2 = instant.toZonedDateTimeISO('Asia/Shanghai');assert.equal(zoned2.epochMilliseconds, legacyDate.getTime());assert.equal(zoned2.timeZoneId, 'Asia/Shanghai');// (And if the legacy Date instance was accessed using the// getUTCFullYear(), getUTCMonth(), etc. methods, consider just// using Instant. If you have to use ZonedDateTime, the specific// time zone may need to be 'UTC'.)3.2 Date => Temporal.PlainDate

一个常见的错误源于这个日期代表什么日期,即年、月、日? 最终结果取决于时区。 旧金山的同一日期可能是 12 月 31 日,伦敦或东京的同一日期可能是 1 月 1 日。

因此,在尝试提取年、月、日之前,在正确的时区上下文中解释日期至关重要。 涉及日期单位。 因此,Temporal.Instant(相当于 Date 的 Temporal)没有年、月、日属性, 要访问 Temporal 中的日期或时间单位,必须提供时区,如上面的代码示例中所述。

另一个容易出现错误的情况是日期被(滥用)用于存储仅日期值,例如:用户的出生日期。 对于日期,这些值通常与午夜时间一起存储,但要正确读回日期则需要知道使用哪个时区的午夜来创建日期。 例如,new Date(2000, 0, 1) 使用调用者的时区,而 new Date('2000-01-01') 使用 UTC。

要正确地将仅日期日期转换为 Temporal.PlainDate,而不容易受到差一天错误的影响,开发者必须确定使用哪个时区的午夜来构造日期,然后在从 Temporal.Instant 到 Temporal.PlainDate。

// 示例 1:将年 / 月 / 日 “Date” 转换为 “Temporal.PlainDate”, 使用调用者时区let date = new Date(2000, 0, 1);// 输出 => Sat Jan 01 2000 00:00:00 GMT-0800 (Pacific Standard Time)let plainDate = date .toTemporalInstant() // => 2000-01-01T08:00:00Z .toZonedDateTimeISO(Temporal.Now.timeZoneId()) // => 2000-01-01T00:00:00-08:00[America/Los_Angeles] .toPlainDate(); // => 2000-01-01assert.equal(plainDate.toString(), '2000-01-01');// 示例 2:将年 / 月 / 日 “Date” 转换为 “Temporal.PlainDate”,使用 UTC。date = new Date(Date.UTC(2000, 0, 1)); // => Fri Dec 31 1999 16:00:00 GMT-0800 (Pacific Standard Time)date = new Date('2000-01-01T00:00Z'); // => Fri Dec 31 1999 16:00:00 GMT-0800 (Pacific Standard Time)plainDate = date .toTemporalInstant() // => 2000-01-01T00:00:00Z .toZonedDateTimeISO('UTC') // => 2000-01-01T00:00:00+00:00[UTC] .toPlainDate(); // => 2000-01-01assert.equal(plainDate.toString(), '2000-01-01');3.3 Temporal 转化为 Date

旧版 Date 表示精确时间,因此可以直接将 Temporal.Instant 或 Temporal.ZonedDateTime 实例转换为与其对应的旧版 Date 实例。

// 使用 epochMilliseconds 属性将 Temporal 转化为 Dateconst instant = Temporal.Instant.from('2020-01-01T00:00:01.000999Z');const result = new Date(instant.epochMilliseconds);assert.equal(result.getTime(), 1577836801000);// ms since Unix epochassert.equal(result.toISOString(), '2020-01-01T00:00:01.000Z');// Same thing for ZonedDateTime.// 请注意,旧版 Date 将不会保留 ZonedDateTime 时区。const zoned = Temporal.ZonedDateTime.from('2020-01-01T00:00:01.001[Asia/Tokyo]');const result2 = new Date(zoned.epochMilliseconds);assert.equal(result2.getTime(), 1577804401001);// note, different timeassert.equal(result2.toISOString(), '2019-12-31T15:00:01.001Z');// 对于大多数用例,new Date(x.epochMilliseconds) 就可以了。// 如果您想要其他步骤,可能需要添加额外的 round() 步骤// 舍入行为比截断行为。 例如,这里的 999// 微秒四舍五入为 1 毫秒。const result3 = new Date(instant.round({ smallestUnit: 'millisecond'}).epochMilliseconds);assert.equal(result3.getTime(), 1577836801001);assert.equal(result3.toISOString(), '2020-01-01T00:00:01.001Z');4.Temporal 的 Polyfill

Temporal Polyfill 是由 Temporal 提案的一些拥护者发起的,目标是在临时提案达到第 4 阶段时为生产使用做好准备,同时该 Polyfill 不隶属于 TC39,同时需要 Node.js 14 或更高版本兼容。

$ npm install @js-temporal/polyfill

CJS 环境中可以通过下面方式使用:

const {Temporal, Intl, toTemporalInstant} = require('@js-temporal/polyfill');Date.prototype.toTemporalInstant = toTemporalInstant;

也可以将 polyfill 作为 ES6 模块导入:

import {Temporal, Intl, toTemporalInstant} from '@js-temporal/polyfill';Date.prototype.toTemporalInstant = toTemporalInstant;

值得注意的是,此 Polyfill 当前不会像真正的实现那样安装全局 Temporal 对象, 此行为避免在存在真实 Temporal 实现的环境中隐藏全局 Temporal 对象。 一旦 JS 引擎开始随 Temporal 一起发布,可能会决定更改此行为以更紧密地匹配内置行为。

同时,此 polyfill 使用 JSBI(JavaScript BigInt) 来实现不支持本机 bigint 的环境的向后兼容性。 如果项目仅在支持本机 bigint 的环境中运行,强烈建议配置 JSBI Babel 插件,将 JSBI 调用转换为其本机 bigint 等效项,从而提高代码大小和性能。

5.本文总结

本文主要和大家介绍 JavaScript 中 Date 的诸多限制,基于这些限制诞生了 Temporal 提案,Temporal 是一个充当顶级命名空间(如: Math)的全局对象,为 ECMAScript 语言带来了更加现代的日期 / 时间 API。因为篇幅问题,关于 Temporal 只是做了一个简短的介绍,但是文末的参考资料提供了大量优秀文档以供学习,如果有兴趣可以自行阅读。如果大家有什么疑问欢迎在评论区留言。

参考资料

https://tc39.es/proposal-temporal/docs/cookbook.html

https://deno.com/blog/v1.40#temporal-api

https://zhuanlan.zhihu.com/p/429908252

https://www.freecodecamp.org/news/javascript-date-time-dayjs/

https://blog.csdn.net/u010454030/article/details/129750173

https://hackernoon.com/dates-in-javascript-are-broken-who-shall-fix-them

https://tc39.es/proposal-temporal/docs/ambiguity.html

https://www.iso.org/iso-8601-date-and-time-format.html

https://www.sitepoint.com/javascript-temporal-api-introduction/

https://github.com/js-temporal/temporal-polyfill

https://refine.dev/blog/temporal-date-api/

https://blog.openreplay.com/is-it-time-for-the-javascript-temporal-api/

0 阅读:0

前有科技后进阶

简介:感谢大家的关注