如何在 date-fns 中仅设置时间并仍然在 javascript 中保留时区

Cha*_*lie 5 timezone datetime date date-fns

我目前有以下用例:

  • 用户从后端收到 UTC 日期
  • 为了显示目的,该日期被转换为当地时间
  • 日期显示在不同的输入中。一个输入用于date,另一个输入用于time
  • 用户可以time自主选择
  • 日期也应该以 UTC 格式发送回后端

我对时区的经验不是很丰富,并且尝试允许用户在日期时间字段中仅设置time(或) 时我被打败了。date

我的伪代码如下:

  • 当从后端接收到数据时,只需转换日期以将其显示给用户,使原始日期保留为 UTC
  • 当用户选择hourand minute(全部在一个操作中)时,使用setHoursandsetMinutesdate-fns库中
  • 使用nativetoISOString()在模型中设置

到目前为止的代码[游乐场]

import { utcToZonedTime, format } from "date-fns-tz";

import { setHours, setMinutes } from "date-fns";

const UTCStringdate = "2022-04-06T10:00:00.000000Z";
const userTimezone = "Asia/Bangkok";
const localizedTime = utcToZonedTime(UTCStringdate, userTimezone);

// Prints the correct information
// 10:00 in UTC is equal to 17:00 in Bangkok
console.log(format(localizedTime, "HH:mm"));

// Now I expext to set only the `minutes` and `hours`
// to this `localizedTime` so that I can update the backend
const [hours, minutes] = "10:30".split(":");

// Somewhere over here the `setHours` and `setMinutes`
// is turning the Date object into my own timezone
// and not using `Asia/Bangkok` timezone anymore
let newTime = setHours(localizedTime, hours);
newTime = setMinutes(newTime, minutes);

// Now I expect to print 17:30 since we only
// set up 30 minutes forward than the original one
// but it ends up printing 10:30
console.log(format(newTime, 'HH:mm'));
Run Code Online (Sandbox Code Playgroud)

我知道在途中的某个地方(最有可能在setHourssetMinutesdate-fns图书馆将背面转回我自己的时区,完全破坏了将时间变成 的localizedTime想法。Asia/BangkokUTC

问题

time首先,在考虑时区时,这是仅操纵日期部分的最佳方法吗?如果没有,谁能给我指点文章?我找不到有关该主题的任何内容

其次,我如何使用setHourssetMinutes维护timezone

och*_*kov 0

JavaScript 中不存在多个时区。有 UTC,也有您当地的 UTC。date-fns-tz 的作用是将时间调整为所选的用户时区。在您的示例中,您可以在打印原始时间和本地时间时看到这一点

const utcTime = new Date(UTCStringdate);
console.log(utcTime.toISOString()); // -> 2022-04-06T10:00:00.000Z
console.log(localizedTime.toISOString()); // -> 2022-04-06T14:00:00.000Z 
Run Code Online (Sandbox Code Playgroud)

要解决您的问题,请将 UTC 时间转换为用户时间,并让用户调整其本地时区的小时和分钟。之后,使用 zonedTimeToUtc 将时间对象转换回 UTC

newTime = zonedTimeToUtc(newTime, userTimezone);
Run Code Online (Sandbox Code Playgroud)

然后使用 newTime.toISOString() 将其发送回服务器。

console.log(newTime.toISOString());
Run Code Online (Sandbox Code Playgroud)