如何解决如何编写一个可以使用 date-fns 将小时和天正确添加到目标时区的函数?
2021-11-07T00:00:00-04:00[美国/纽约]
注意:这个时间戳是 2 hours away 从 DST 过渡到标准时间。
我想编写一个函数,它可以接受时间戳、时区标识符和 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",{
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,duration: Duration
) => {
const startDate = parseISO(isoDateStr);
const zonedTime = utcToZonedTime(startDate,zoneIana);
const futureDate = add(zonedTime,duration);
return formatTz(futureDate,{
timeZone: zoneIana
});
};
您可能会注意到,zonedAddDuration1
和 zonedAddDuration2
之间的唯一区别是我使用 utcToZonedTime
的顺序。我需要这个函数是通用的,并且应该正确处理各种持续时间,包括 DST 转换。我应该补充一点,系统的本地时区应该无关紧要,无论我在哪里运行此代码,我都希望得到相同的结果。
我认为我对 date-fns-tz 的理解可能有所欠缺,我已经阅读了 the documentation 多次,但仍然不确定我是否理解正确。
如果无法编写这样的函数,那么将不胜感激(为什么排序很重要)。
我一直在这个 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
});
};
Here is a Codesandbox 带有工作版本和测试。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。