date-fns-tz の挙動についてメモ

date-fns-tz の utcToZonedTime
と zonedTimeToUtc
の挙動が思ったのと違ったので、メモしとく。
以下の script 用意
import utcToZonedTime from 'date-fns-tz/utcToZonedTime';
import zonedTimeToUtc from 'date-fns-tz/zonedTimeToUtc';
const now = new Date();
console.log(now);
console.log(utcToZonedTime(now, 'Asia/Tokyo')); // + 9時間になるはず
console.log(zonedTimeToUtc(now, 'Asia/Tokyo')); // - 9時間になるはず
tsx で実行していく
タイムゾーン: UTC
TZ=UTC npx tsx main.ts
2023-03-30T14:02:00.174Z
2023-03-30T23:02:00.174Z
2023-03-30T05:02:00.174Z
=> 想定通り
タイムゾーン: Asia/Tokyo
TZ=Asia/Tokyo npx tsx main.ts
2023-03-30T14:00:41.886Z
2023-03-30T14:00:41.886Z
2023-03-30T14:00:41.886Z
=> 想定と違う。変わってない...!!!
タイムゾーン: America/New_York
TZ=America/New_York npx tsx main.ts
2023-03-30T14:07:01.441Z
2023-03-31T03:07:01.441Z
2023-03-30T01:07:01.441Z
=> 想定と違う。13 時間変わっている...

Working with UTC or ISO date strings is easy, and so is working with JS dates when all times are displayed in a user's local time in the browser. The difficulty comes when working with another time zone's local time, one other than the current system's, like on a Node server or when showing the time of an event in a specific time zone, like an event in LA at 8pm PST regardless of where a user resides.
実行環境のタイムゾーンと異なるタイムゾーンの時刻を同時に扱うケースでつかうべきもの、ってことか?

同じところで詰まってたのですが、対象のタイムゾーンとローカルのタイムゾーンとのオフセットを足したり引いたりするような挙動のようですね
TZ=UTC(オフセット 0) のときは日本時間(オフセット 9時間)とのオフセットが 9 時間あるので、9時間を足したり引いたりする一方で、
TZ=Asia/Tokyo(オフセット 9時間)のときは日本時間(オフセット 9時間)とのオフセットが 0 なので、各関数を通しても変化がない
utcTo や ToUtc を localTimezoneTo / ToLocalTimezone と脳内で読み替えて利用してました