[英]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.