javascript 如何在特定日期和时间创建'Temporal.Instant'示例?

uqjltbpv  于 2022-12-10  发布在  Java
关注(0)|答案(2)|浏览(103)

我正在努力解决JavaScript的proposed new Temporal API。我试图做的事情应该是直截了当的,但我没有找到一个令人信服的解决方案。我一定是错过了什么。
任务如下:从年、月、日、小时和分钟变量示例化UTC日期时间对象表示
我的想法如下:

  • 我们讨论的是UTC,因此我需要Temporal.Instant;
  • new Temporal.Instant()需要以纳秒为单位的时间戳,因此无法工作;
  • Temporal.Instant.from()需要一个ISO日期时间字符串,这需要我从我拥有的五个变量中生成一段格式正确的文本--这是可能的,但有点麻烦,有点违背了使用日期时间库的目的;
  • Temporal.PlainDateTime.from()具有正确的设计,因为它接受像{ year, month, day, hour, minute }这样的对象;
  • 因此,我们需要做的就是从这个PlainDateTime创建一个Instant。这似乎是不可能的,虽然?除了通过-再次-一个日期时间字符串或时间戳在ns...?

这是愚蠢的!这里的用例是超级基本的,但它不明显(对我来说)在所有如何解决它。
我希望能够简单地做一些像这样的事情:Temporal.Instant.from({ year, month, day, hour, minute });
现在我能想到的最好的办法是:Temporal.Instant.from(year + '-' + String(month).padStart(2, '0') + '-' + String(day).padStart(2, '0') + 'T' + String(hour).padStart(2, '0') + ':' + String(minute).padStart(2, '0') + 'Z'); // 😱
拜托告诉我我是不是忽略了什么。

ql3eal8s

ql3eal8s1#

您的PlainDateTime表示“a calendar date and wall-clock time that does not carry time zone information"。若要将它转换为精确的时间,您需要使用toZonedDateTime方法提供一个时区。然后通过toInstant方法忽略日历和时区,您可以获得所需的Instant示例。
有几种方法可以实现这一点:

  • 从对象创建PlainDateTime,通过假定UTC时区将其转换为instant:
Temporal.PlainDateTime.from({year, month, day, hour, minute}).toZonedDateTime("UTC").toInstant()
  • 使用建构函式建立PlainDateTime,并假设UTC时区,将它转换为即时:
new Temporal.PlainDateTime(year, month, day, hour, minute).toZonedDateTime("UTC").toInstant()
  • 直接从一个对象创建一个ZonedDateTime,在其中提供时区,然后转换它:
Temporal.ZonedDateTime.from({timeZone: 'UTC', year, month, day, hour, minute}).toInstant()
  • 除了通过一个分区的日期时间,您还可以获得TimeZone示例归属于PlainDateTime对象的时刻:
Temporal.TimeZone.from("UTC").getInstantFor(Temporal.PlainDateTime.from({year, month, day, hour, minute}))
new Temporal.TimeZone("UTC").getInstantFor(new Temporal.PlainDateTime(year, month, day, hour, minute))
  • 如果您想在代码中硬编码instant,也可以直接从ISO字符串创建它:
Temporal.Instant.from("2022-10-23T02:50Z")
  • 如果您愿意包含旧的Date方法,您也可以使用Date.UTC来计算即时月份的毫秒值-注意从零开始的月份:
Temporal.Instant.fromEpochMilliseconds(Date.UTC(year, month-1, day, hour, minute));

用你自己的例子来试试:
第一个

rm5edbpk

rm5edbpk2#

  • Date* API将永远存在,而且非常方便,因此如果有帮助,使用它似乎是明智的。
  • Date.UTC* 返回自ECMAScript纪元以来的毫秒数。Temporal.instant 需要纳秒,因此给定一个{year, month, day, etc.}的输入对象,唯一的麻烦是使用BigInt处理纳秒,这并不难:
// Object for 7 December 2022
let d = {
  year: 2022,
  month: 12,
  day: 7,
  hour: 3,
  minute: 24,
  second: 30,
  millisecond: 10,
  microsecond: 3,
  nanosecond: 500
}

// Convert to time value - nanoseconds since ECMAScript eopch
let timeValue = BigInt(Date.UTC(d.year, d.month-1, d.day, 
  d.hour, d.minute, d.second, d.millisecond)) * BigInt(1e6) +
  BigInt(d.microsecond * 1e3) + BigInt(d.nanosecond);

// 1670383470010003500
console.log(timeValue.toString());

// 2023-01-07T03:24:30.010Z
console.log(new Date(Number(timeValue/BigInt(1e6))).toISOString());

然后,可以创建一个 instant

let instant = new Temporal.Instant(timeValue);

相关问题