[英]How to write a function that can add hours and days correctly to the target time zone with date-fns?
假设我有一个带有 IANA 时区标识符的时间戳:
2021-11-07T00:00:00-04:00[美国/纽约]
注意:此时间戳是从 DST 转换到标准时间的2 小时。
我想编写一个 function 可以获取时间戳、时区标识符和Duration ,并在目标时区返回一个新的“未来”时间戳。
例如:
zonedAddDuration("2021-11-07T00:00:00-04:00", "America/New_York", {
days: 1
})
// => "2021-11-08T00:00:00-05:00"
zonedAddDuration("2021-11-07T00:00:00-04:00", "America/New_York", {
hours: 5
})
// "2021-11-07T04:00:00-05:00"
我似乎找到了一种让zonedAddDuration
处理这两种情况的方法,但不能同时处理:
import { add, Duration, parseISO } from "date-fns";
import {
utcToZonedTime,
format as formatTz
} from "date-fns-tz";
// Handles "hours" scenario (also minutes and seconds)
export const zonedAddDuration1 = (
isoDateStr: string,
zoneIana: string,
duration: Duration
) => {
const startDate = parseISO(isoDateStr);
const futureDate = add(startDate, duration);
const zonedTime = utcToZonedTime(futureDate, zoneIana);
return formatTz(zonedTime, "yyyy-MM-dd'T'HH:mm:ssXXXzzz", {
timeZone: zoneIana
});
};
// handles "days" scenario (also months, weeks, years)
export const zonedAddDuration2 = (
isoDateStr: string,
zoneIana: string,
duration: Duration
) => {
const startDate = parseISO(isoDateStr);
const zonedTime = utcToZonedTime(startDate, zoneIana);
const futureDate = add(zonedTime, duration);
return formatTz(futureDate, "yyyy-MM-dd'T'HH:mm:ssXXXzzz", {
timeZone: zoneIana
});
};
您可能会注意到, zonedAddDuration1
和zonedAddDuration2
之间的唯一区别是我使用utcToZonedTime
的顺序。 我需要这个 function 是通用的,并且应该正确处理各种持续时间,包括 DST 转换。 我应该补充一点,系统的本地时区应该无关紧要,无论我在哪里运行此代码,我都想要相同的结果。
我认为我可能缺乏对 date-fns-tz 的理解,我已经阅读了很多次文档,但仍然不确定我是否正确掌握了它。
如果不可能写出这样的 function,那么任何帮助理解它为什么会这样表现将不胜感激(为什么排序很重要)。
我一直在这个 Codesandbox(包括 2 个测试场景)中进行试验: https://codesandbox.io/s/exciting-fog-tke86?file=/src/dateUtil.ts
我找到了一种可以为日期和时间正确添加持续时间的方法。 我所做的是将输入持续时间拆分为持续时间和日期持续时间,并将它们分别添加到输入日期。 这样,我可以在两种情况下以正确的顺序应用utcToZonedTime
。
尽管如此,所有这一切都感觉像是一种黑客行为,我仍然不确定它为什么会起作用(或者即使它在所有可能的场景中都能按预期工作)。
import { add, Duration, parseISO } from "date-fns";
import {
utcToZonedTime,
format as formatTz
} from "date-fns-tz";
export const zonedAddDuration = (
isoDateStr: string,
zoneIana: string,
duration: Duration
) => {
const startDate = parseISO(isoDateStr);
const dateDuration: Duration = {
years: duration.years ?? 0,
months: duration.months ?? 0,
weeks: duration.weeks ?? 0,
days: duration.days ?? 0
};
const timeDuration: Duration = {
hours: duration.hours ?? 0,
minutes: duration.minutes ?? 0,
seconds: duration.seconds ?? 0
};
const futureDateTime = add(startDate, timeDuration);
const zonedTime = utcToZonedTime(futureDateTime, zoneIana);
const futureDate = add(zonedTime, dateDuration);
return formatTz(futureDate, "yyyy-MM-dd'T'HH:mm:ssXXXzzz", {
timeZone: zoneIana
});
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.