簡體   English   中英

如何編寫一個 function 可以使用 date-fns 正確地將小時和天添加到目標時區?

[英]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
  });
};

您可能會注意到, zonedAddDuration1zonedAddDuration2之間的唯一區別是我使用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
  });
};

這是一個帶有工作版本和測試的 Codesandbox

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM