正しい日付と時刻を表示する
フレームの表示内容は、実際に表示される少し前に準備されます。ウィジェットが正しい時刻を表示できるよう、時計はフレームに表示される瞬間まで進めてあります。new Date()やDate.now()はその瞬間を返すので、特別なことは何もする必要がありません。
import { useTimeZone } from "~lib/use-time-zone";
export const Widget = () => {
const timeZone = useTimeZone();
return (
<h1>
{new Date().toLocaleTimeString(undefined, {
timeZone,
hour: "2-digit",
minute: "2-digit",
})}
</h1>
);
};
時刻を書式化するときは、必ずuseTimeZoneで取得したフレームのタイムゾーンを渡してください。ウィジェットを描画するブラウザーはフレームのタイムゾーンにはないため、getHours()を使ったり、timeZoneを指定せずに書式化したりすると、プレビューでは正しく見えても、フレームでは時刻がずれてしまいます。
0時に表示するために準備されたフレームには0時が表示され、「今日」はフレームに表示される日を指します。ウィジェットスタジオのプレビューでは、単に現在の時刻になります。
日付の文字列を解析する場合など、new Date(...)に値を渡したときは、いつもどおりに動作します。
取得するデータ
ウィジェットがデータを取得するのは、フレームの表示内容が準備されるとき、つまり表示される少し前です。ほとんどの場合は違いが出ませんが、日付を指定しなくても「今日」の天気予報を返すAPIの場合、0時の直前に準備されたフレームには前日の予報が返ってきます。
必要な日付を指定してリクエストするか、new Date()を使って結果から選び出してください。
import { useFetch } from "~lib/use-fetch";
import { useTimeZone } from "~lib/use-time-zone";
type Forecast = {
readonly days: { readonly date: string; readonly high: number }[];
};
export const Widget = () => {
const timeZone = useTimeZone();
const { data } = useFetch<Forecast>(
"https://api.example.com/forecast?days=2",
);
// フレームに表示される日。APIの日付に合わせて、2030-01-31の形式で書きます。
const today = new Date().toLocaleDateString("en-CA", { timeZone });
const forecast = data.days.find((day) => day.date === today) ?? data.days[0];
return <h1>{forecast.high}°</h1>;
};
フック
時刻を読み取るのにフックは必要ありませんが、厳密に扱いたいときのために2つ用意されています。
useScheduledDateは、フレームに表示される瞬間を返します。そのことをコードの上でもはっきりさせたいときに使います。useRenderDateは、フレームの表示内容が実際に準備されている時刻を返します。署名付きリクエストのように、送られたタイムスタンプをAPI自身の時計と照合する、まれなケースで使います。