ローカル時刻表示
stimeo--local-time
サーバが出した UTC の時刻を、閲覧者の時間帯と言語で表示します。
サーバは UTC のまま時刻を出しておき、表示だけを閲覧者の時間帯と言語に合わせます。サーバが相手の時間帯を知る必要がないので、生成した HTML をそのままキャッシュできます。整形にはブラウザが持っている機能を使うので、依存は増えません。機械が読む値は書き換えないので、読み上げや検索の側から見た正しさは保たれます。時刻や時間帯が読めないときは、元の表示のまま残します。「3 分前」のような言い方が欲しいときは、相対時刻の部品を使ってください。
- 公開 UTC 2026-06-08 12:30
- リリース UTC 2026-01-01 09:00
- 開始 UTC 2026-12-24 21:00
- 現在 UTC 2026-09-20 06:22
どの時刻も UTC のまま置かれていて、表示だけがあなたの時間帯と言語に合わせられています。同じ瞬間でも、別の時間帯の人には別の時計の値に見えます。カーソルを合わせると、より詳しい形が出ます。
キーボード操作
このコンポーネント自体はキーボード操作を持ちません。
<%# Markup for the local-time demo.
Each <time> carries a machine-readable UTC datetime; the controller reformats the
visible text into the viewer's locale and timezone via Intl.DateTimeFormat, leaving
the datetime attribute (the screen-reader / SEO value) intact. The locale follows the
page language and the timezone follows the browser, so the server can emit plain UTC
and stay cacheable. The last row clears the time style to show a date-only format. %>
<% rows = [
{ at: Time.utc(2026, 6, 8, 12, 30), key: "published", date: "medium", time: "short" },
{ at: Time.utc(2026, 1, 1, 9, 0), key: "released", date: "full", time: "short" },
{ at: Time.utc(2026, 12, 24, 21, 0), key: "starts", date: "long", time: "" },
{ at: Time.now.utc, key: "now", date: "medium", time: "medium" }
] %>
<ul class="local-time-demo">
<% rows.each do |row| %>
<li class="local-time-demo__row">
<span class="local-time-demo__label">
<%= t("components.local_time.demo.#{row[:key]}") %>
</span>
<span class="local-time-demo__convert">
<span class="local-time-demo__source">UTC <%= row[:at].strftime("%Y-%m-%d %H:%M") %></span>
<span class="local-time-demo__arrow" aria-hidden="true">→</span>
<time
class="local-time"
data-controller="stimeo--local-time"
datetime="<%= row[:at].iso8601 %>"
data-stimeo--local-time-locale-value="<%= I18n.locale %>"
data-stimeo--local-time-date-style-value="<%= row[:date] %>"
data-stimeo--local-time-time-style-value="<%= row[:time] %>"
data-stimeo--local-time-title-format-value="long">
<%= row[:at].strftime("%Y-%m-%d %H:%M UTC") %>
</time>
</span>
</li>
<% end %>
</ul>
<p class="local-time-demo__hint"><%= t("components.local_time.demo.hint") %></p>
/*
* Presentation-only styles for the local-time demo.
* The library only replaces the element's text with the localized absolute time
* (and adds a detailed title); the machine-readable datetime attribute is kept.
*/
.local-time-demo {
margin: 0;
padding: 0;
list-style: none;
display: flex;
flex-direction: column;
gap: 0.5rem;
max-width: 46rem;
}
.local-time-demo__row {
display: flex;
align-items: baseline;
justify-content: space-between;
gap: 1rem;
/* Keep the label and value on one line when there's room; on a genuinely narrow
stage the value group drops to a second line as a whole — never mid-value
(see the nowrap rules below), which is what made English look cluttered. */
flex-wrap: wrap;
padding: 0.5rem 0.75rem;
border: 1px solid var(--border);
border-radius: 0.375rem;
}
.local-time-demo__label {
color: var(--muted);
font-size: 0.9rem;
}
.local-time-demo__convert {
display: flex;
align-items: baseline;
gap: 0.5rem;
white-space: nowrap;
}
/* The source UTC, shown next to the localized time so the conversion is verifiable. */
.local-time-demo__source {
color: var(--muted);
font-size: 0.8rem;
font-variant-numeric: tabular-nums;
white-space: nowrap;
}
.local-time-demo__arrow {
color: var(--muted);
}
/* The localized absolute time. An English full date is long, so keep it on one
line and let the row (not the time) wrap when space is tight. */
.local-time {
font-variant-numeric: tabular-nums;
color: var(--fg);
white-space: nowrap;
}
/* Explanatory caption: the time is localized on the client from the UTC datetime. */
.local-time-demo__hint {
margin: 0.75rem 0 0;
max-width: 46rem;
font-size: 0.85rem;
line-height: 1.5;
color: var(--muted);
}
このデモに固有の消費側 JS はありません(挙動はコントローラが担います)。
これらのスタイルは共通のデザイントークン(ライト/ダーク両対応)を使います。共通スタイルも一緒にコピーし、ルート要素の data-theme を切り替えればダークになります。
このコンポーネントを動かすために HTML へ記述する data-* 属性です。ルート要素に下の data-controller を付け、その内側に各 target / value / action を配置します。
ルート要素に付与
data-controller="stimeo--local-time"
値(Values)
| 名前 | 説明 | 属性 |
|---|---|---|
locale
|
Intl.DateTimeFormat のロケール。空なら要素の lang、次に文書の lang。既定は空。 |
data-stimeo--local-time-locale-value |
timeZone
|
IANA タイムゾーン。空ならブラウザ既定。 | data-stimeo--local-time-time-zone-value |
dateStyle
|
Intl の dateStyle(full/long/medium/short)。空で日付を省略(既定 medium)。 |
data-stimeo--local-time-date-style-value |
timeStyle
|
Intl の timeStyle(full/long/medium/short)。空で時刻を省略(既定 short)。 |
data-stimeo--local-time-time-style-value |
titleFormat
|
title 用に日付と時刻の両方へ適用する Intl スタイル。空なら title を付けない(既定空)。 | data-stimeo--local-time-title-format-value |
イベント
| 名前 | 説明 | イベント |
|---|---|---|
format
|
整形後に発火。detail.formatted を伴う。 |
stimeo--local-time:format |
状態フック
ライブラリが操作するのはこれらの ARIA / data 属性、カスタムプロパティだけです。見た目は利用側 CSS がこれらに反応して作ります([aria-selected] / [aria-expanded] / var(--stimeo--…) などのセレクタでフックします)。
| フック | 対象 | 意味 |
|---|---|---|
テキスト |
ルート要素 | ローカライズされた絶対時刻。 |
title |
ルート要素 | 任意の詳細形(titleFormat を設定したとき)。 |
datetime |
ルート要素 | 機械可読な UTC 値(不変)。 |