date-fns / tz

date-fns timezone utils
MIT License
88 stars 5 forks source link

`in` doesn't work at all (or at least not as expected). #31

Open janhesters opened 4 days ago

janhesters commented 4 days ago

I'm trying to set the time of a date in a specific timezone:

      date: new TZDate('2024-01-15T00:00:00.000Z', 'America/New_York'),
      time: '09:30',
      expected: new TZDate('2024-01-15T09:30:00.000-05:00', 'America/New_York'),

Basically I want a function, that given aTZDate and a time in HH:mm, sets that time on the date, but preserves the date in the timezone.

Here is the code I wrote:

export function combineDateAndTime({
  date,
  time,
}: {
  date: TZDate;
  time: string;
}): TZDate {
  // Validate the input date.
  if (Number.isNaN(date.getTime())) {
    throw new TypeError('Invalid date format');
  }

  // Parse the time string.
  const timeMatch = /^(\d{1,2}):(\d{2})$/.exec(time);
  if (!timeMatch) {
    throw new TypeError('Invalid time format');
  }

  // Validate hours and minutes.
  const hours = Number.parseInt(timeMatch[1], 10);
  const minutes = Number.parseInt(timeMatch[2], 10);
  if (hours < 0 || hours > 23 || minutes < 0 || minutes > 59) {
    throw new TypeError('Invalid time format');
  }

  // Create the new TZDate instance.
  console.log('date', date);
  console.log('date.timeZone', date.timeZone);
  console.log('tz(date.timeZone!)', tz(date.timeZone!));
  const result = setMilliseconds(
    setMinutes(setHours(date, hours, { in: tz(date.timeZone!) }), minutes, {
      in: tz(date.timeZone!),
    }),
    0,
    { in: tz(date.timeZone!) },
  );
  console.log('result', result);
  return result;
}

Actual

date TZDate 2024-01-15T00:00:00.000Z {
  timeZone: 'America/New_York',
  internal: 2024-01-14T19:00:00.000Z
}
date.timeZone America/New_York
tz(date.timeZone!) [Function (anonymous)]
result TZDate 2024-01-14T14:30:00.000Z {
  timeZone: 'America/New_York',
  internal: 2024-01-14T09:30:00.000Z
}

Expected

date TZDate 2024-01-15T00:00:00.000Z {
  timeZone: 'America/New_York',
  internal: 2024-01-14T19:00:00.000Z
}
date.timeZone America/New_York
tz(date.timeZone!) [Function (anonymous)]
result TZDate 2024-01-15T9:30:00.000Z {
  timeZone: 'America/New_York',
  internal: 2024-01-15T14:30:00.000Z
}
myang5 commented 1 day ago

Having similar issues, in converting code from moment.js that is determining whether multiple dates have the same hour across DST.

// Two dates with different hours in UTC, but should be the same hour
// when set to an American timezone because of DST
console.log(format('2021-03-09T10:00:00Z', 'E HH mm', { in: tz('America/New_York') }));
console.log(format('2021-04-06T09:00:00Z', 'E HH mm', { in: tz('America/New_York') }));
console.log(format('2021-03-09T10:00:00Z', 'E HH mm', { in: tz('America/Los_Angeles') }));
console.log(format('2021-04-06T09:00:00Z', 'E HH mm', { in: tz('America/Los_Angeles') }));

Actual:

// Is just outputting the values in UTC
Tue 10 00
Tue 09 00
Tue 10 00
Tue 09 00

Expected:

Tue 05 00
Tue 05 00
Tue 02 00
Tue 02 00