ProduktionGilt fürLite und Pro
Sprachen, Kalenderdaten und Zeitzonen
Setzen Sie `locale` auf eine beliebige Intl-Locale-ID wie `fr-fr`: Monats- und Tagesnamen, die 12- oder 24-Stunden-Uhr und der erste Wochentag richten sich danach, und `timeFormat` und `weekStarts` überschreiben die letzten beiden. Datumswerte sind bürgerliche Wanduhrzeiten: Der Planer rechnet nie Zeitzonen um und expandiert nie wiederkehrende Ereignisse. Rechnen Sie Zeitpunkte in die Zeitzone des Geschäfts um, bevor Sie Ereignisse übergeben, rechnen Sie beim Speichern zurück und expandieren Sie Serien in Ihrer Anwendung zu einzelnen Vorkommen.
Ein Planer zeigt Menschen Datumsangaben; deshalb treffen hier zwei getrennte Fragen aufeinander. Die Lokalisierung entscheidet, wie ein Datum geschrieben wird: Namen, Reihenfolge, Uhr und erster Wochentag. Die Zeitsemantik entscheidet, welches Datum es ist: Die Bibliothek arbeitet mit Wanduhrzeiten in bürgerlicher Zeit und überlässt Zeitzonen und Wiederholungen Ihrer Anwendung. Diese Anleitung behandelt beides, für Pro und, wo vermerkt, für Lite.
Die Locale festlegen
locale akzeptiert jede Locale-ID, die Intl versteht, im Stil von SuperScheduler kleingeschrieben: en-us (der Standard), en-gb, fr-fr, de-de, es-es, pt-br, nl-nl, ja-jp und so weiter. Es gibt keine Liste, in die Sie sich eintragen müssten. en_US wird zu en-us normalisiert, und eine ID, die Intl nicht auflösen kann, fällt auf en-us zurück.
In Pro steuert die Locale:
- die Monats- und Tagesnamen in den Standard-Zeitköpfen und in jedem
format-Muster eines Kopfes; - die Standarduhr, wenn
timeFormatauf'Auto'steht (12 Stunden füren-us, 24 Stunden für die meisten europäischen Locales); - den ersten Wochentag, wenn
weekStartsauf'Auto'steht (Sonntag füren-usundpt-br, Montag für die meisten europäischen Locales); - die Standard-Datumsmuster der Tagesköpfe und die Datumsangaben auf der Ziehkarte;
- die Sprache der Tastaturansagen und einiger eingebauter Beschriftungen (siehe Eingebaute Texte).
Lite akzeptiert dieselben locale-IDs für seine Tagesköpfe.
import { useCallback, useState } from 'react'
import { SuperScheduler, SuperSchedulerComponent } from 'super-scheduler'
import type { SchedulerEventClickArgs } from 'super-scheduler'
// One constant for the scheduler and for every date you format yourself.
const LOCALE = 'fr-fr'
const WEEK_START = SuperScheduler.Date.today().firstDayOfWeek(1)
const TIME_HEADERS: SuperScheduler.TimeHeaderData[] = [
{ groupBy: 'Day', format: 'dddd d MMMM' }, // "lundi 5 octobre"
{ groupBy: 'Hour' }, // default labels follow timeFormat: "0" to "23" here, "2 PM" in 12-hour mode
]
interface Props {
readonly rooms: SuperScheduler.ResourceData[]
readonly events: SuperScheduler.EventData[]
}
export function FrenchPlanning({ rooms, events }: Props) {
const [summary, setSummary] = useState('')
// SuperScheduler.Date#toString does not read the scheduler's locale: pass it explicitly.
const onEventClick = useCallback((args: SchedulerEventClickArgs) => {
const start = args.e.start().toString('dddd d MMMM, HH:mm', LOCALE)
const end = args.e.end().toString('HH:mm', LOCALE)
setSummary(`${args.e.text()} : ${start} – ${end}`)
}, [])
return (
<>
<p aria-live="polite">{summary}</p>
<SuperSchedulerComponent
locale={LOCALE}
// 'Auto' already gives Monday and a 24-hour clock for fr-fr; explicit values ignore the locale.
weekStarts={1}
timeFormat="Clock24Hours"
startDate={WEEK_START}
days={7}
scale="Hour"
cellWidth={48}
timeHeaders={TIME_HEADERS}
resources={rooms}
events={events}
onEventClick={onEventClick}
/>
</>
)
}Sie sollten Köpfe wie „lundi 5 octobre“ über Stundenspalten mit den Beschriftungen 0 bis 23 sehen, eine Woche, die am Montag beginnt, und eine französische Zusammenfassung, wenn Sie auf ein Ereignis klicken.
Uhrformat und erster Wochentag
timeFormat akzeptiert 'Auto', 'Clock12Hours' oder 'Clock24Hours'. Es ändert nur die Standardbeschriftungen der Stunden; ein explizites format in timeHeaders hat immer Vorrang ('HH:mm' für 24 Stunden, 'h:mm tt' für 12 Stunden). Es ist eine Anzeigeeinstellung, keine Zeitumrechnung: Ein Umschalten verschiebt nie ein Ereignis.
weekStarts akzeptiert 'Auto' oder eine Tagesnummer von 0 (Sonntag) bis 6 (Samstag). Es wirkt sich auf Week-Zellen und Kopfgruppen aus, auf die Wochenlinien, die beim Herauszoomen gezeichnet werden, und auf die Standard-Wochennummern: ISO-Nummern, wenn Wochen am Montag beginnen, sonst US-Nummern. In Ihrem eigenen Code verwendet date.firstDayOfWeek() standardmäßig Sonntag; übergeben Sie daher denselben Wert (firstDayOfWeek(1)) oder die Locale-ID (firstDayOfWeek('fr-fr')).
Worauf 'Auto' bei einigen IDs hinausläuft:
| Locale | ddd d MMM | Uhr | Woche beginnt am |
|---|---|---|---|
en-us | Mo 5 Oct | 12 Stunden | Sonntag |
en-gb | Mo 5 Oct | 24 Stunden | Montag |
es-es | L 5 oct | 24 Stunden | Montag |
de-de | Mo 5 Okt | 24 Stunden | Montag |
fr-fr | lu 5 oct. | 24 Stunden | Montag |
pt-br | se 5 out. | 24 Stunden | Sonntag |
Datumswerte in Ihrer eigenen Oberfläche formatieren
SuperScheduler.Date formatiert mit den Mustern von SuperScheduler: yyyy, yy, MMMM, MMM, MM, M, dddd, ddd, dd, d, HH, H, hh, h, mm, m, ss, s und tt (AM/PM). Alles andere ist wörtlicher Text.
ddd ist der kurze Wochentagsname aus Intl, der in mehreren Locales aus einem oder zwei Buchstaben besteht: „Mo“ auf Englisch, „L“ auf Spanisch, „lu“ auf Französisch, „dl“ auf Katalanisch. Verwenden Sie dddd für den vollen Namen, registrieren Sie eigene Kurznamen (siehe unten) oder formatieren Sie direkt mit Intl. date.toDate() gibt ein natives Date mit denselben Ticks zurück, das in UTC gelesen werden soll; formatieren Sie es daher mit timeZone: 'UTC', um auf jedem Gerät genau den Wert in bürgerlicher Zeit anzuzeigen:
import type { SuperScheduler } from 'super-scheduler'
// toDate() returns a native Date with the same ticks, meant to be read in UTC.
// Formatting it with timeZone 'UTC' shows exactly the civil value, on any device.
const dayFormat = new Intl.DateTimeFormat('fr-FR', {
weekday: 'short',
day: 'numeric',
month: 'short',
timeZone: 'UTC',
})
const stayFormat = new Intl.DateTimeFormat('en-GB', {
day: 'numeric',
month: 'short',
hour: '2-digit',
minute: '2-digit',
timeZone: 'UTC',
})
export function formatDay(date: SuperScheduler.Date): string {
return dayFormat.format(date.toDate()) // "lun. 5 oct."
}
export function formatStay(start: SuperScheduler.Date, end: SuperScheduler.Date): string {
return stayFormat.formatRange(start.toDate(), end.toDate())
}Eigene Namen und Muster
SuperScheduler.Locale.register() ersetzt die Namen und Muster einer ID für jeden Planer und jeden Aufruf von toString, der sie verwendet. Eine SuperScheduler.Locale, die direkt als Option locale übergeben wird, wird automatisch registriert.
import { SuperScheduler } from 'super-scheduler'
// Start from the Intl data for the id: fields you leave out fall back to US English, not to French.
const base = SuperScheduler.Locale.find('fr-fr')
// Run once at startup, before the first scheduler mounts.
SuperScheduler.Locale.register(
new SuperScheduler.Locale('fr-fr', {
...base,
// `ddd` gives two-letter Intl abbreviations ("lu"); these read "lun.".
dayNamesShort: ['dim.', 'lun.', 'mar.', 'mer.', 'jeu.', 'ven.', 'sam.'],
}),
)
// Every scheduler with locale="fr-fr" and every toString(pattern, 'fr-fr') now uses these names.
export const sample = new SuperScheduler.Date('2026-10-05').toString('ddd d MMM', 'fr-fr') // "lun. 5 oct."Eingebaute Texte und ihre Sprachen
Die Bibliothek schreibt einige eigene Texte. Die Sprache ist der erste Teil der Locale-ID (ca-es ergibt ca).
| Texte | Sprachen | Überschreiben |
|---|---|---|
| Tastaturansagen und Fokusbeschriftungen | Englisch, Spanisch, Katalanisch, Baskisch, Galicisch, Deutsch, Französisch, Italienisch, Portugiesisch | Nicht konfigurierbar |
| Dauern und Ablehnungen auf der Ziehkarte („2 nights“, „Overlaps“, „Not allowed“) | Dieselben neun Sprachen | dragCard={{ labels: { ... } }} |
| Name des Rasters, Lade-, Leer- und Fehlertexte | Englisch, oder Spanisch für es-Locales | emptyState, errorState und loadingLabelText; der barrierefreie Name des Rasters ist fest |
| Beschriftungen der Verlaufseinträge („Move“, „Resize“) | Englisch, oder Spanisch für es-Locales | createHistory({ labels }) |
| Beschriftungen der Minimap | Englisch, oder Spanisch für es-Locales | createMinimap(control, element, { labels }) oder die Prop labels von SchedulerMinimap |
| Badge für die Detailstufe | Englisch, oder Spanisch für es-Locales | drittes Argument von createLodBadge |
| Lite: Beschriftung des Rasters und Leertext | Englisch | ariaLabel, emptyState |
Jede andere Sprache erhält Englisch; eine französische oder deutsche Anwendung sollte daher eigene Texte für Verlauf, Minimap, Badge und Statustexte übergeben. Ereignistexte, Ressourcennamen und jegliches HTML, das Sie rendern, übersetzen Sie selbst.
Bürgerliche Zeit
Jedes Datum in SuperScheduler ist ein Wert in bürgerlicher Zeit, also eine Wanduhrzeit ohne Zeitzone. '2026-10-01T10:00:00' bedeutet zehn Uhr auf der Planungstafel, egal wo die Seite geöffnet wird. Die Folgen:
- Strings brauchen Sekunden.
'2026-10-01'und'2026-10-01T10:00:00'sind gültig;'2026-10-01T10:00'wirft „is not an ISO 8601 date“. NativeDate-Objekte bestehen die Typprüfung fürstartoderendnicht. - Zonen werden in UTC umgerechnet. Ein String mit
Zoder einem Offset wird in die UTC-Wanduhrzeit umgerechnet:'2026-10-01T10:00:00+02:00'wird zu08:00:00. Entfernen Sie Zonenangaben erst, nachdem Sie selbst in die Zeitzone des Geschäfts umgerechnet haben. - Keine Überraschungen durch die Sommerzeit.
2026-03-29T02:30:00existiert, und eine Stunde darauf ergibt03:30, unabhängig von der Zeitzone des Browsers. Dauern sind einfache Differenzen von Wanduhrzeiten. - Intervalle sind halboffen. Ein Ereignis von
14:00bis16:00endet vor einer Buchung, die um16:00beginnt. - Native Datumswerte.
new SuperScheduler.Date(date)liest die UTC-Felder eines nativenDate;new SuperScheduler.Date(date, true)liest seine lokalen Felder.toDate()gibt einDatezurück, das in UTC zu lesen ist;toDateLocal()gibt eines zurück, dessen lokale Felder die Wanduhrzeit zeigen. - „Heute“ ist das Gerät des Betrachters.
SuperScheduler.Date.today(), der Standardwert vonstartDate, die Hervorhebung von heute und die Jetzt-Linie verwenden die Uhr des Geräts. Wer in New York ein Hotel in Madrid plant, sieht das Heute von New York. Wenn das wichtig ist, berechnen Sie das „Heute“ des Geschäfts selbst und übergeben es alsstartDateoder anscrollTo.
Zeitzonen sind Sache Ihrer Anwendung
Wenn Ihr Backend Zeitpunkte speichert (UTC-Zeitstempel), wählen Sie die Zeitzone, die ein Planer jeweils darstellt, meist die des Standorts oder des Ressourceninhabers, und rechnen an den Rändern um. Intl.DateTimeFormat mit einer timeZone liefert Ihnen die Wanduhrzeit jedes Zeitpunkts, ohne zusätzliche Abhängigkeit:
import { SuperScheduler } from 'super-scheduler'
const formatters = new Map<string, Intl.DateTimeFormat>()
function partsFormatter(timeZone: string): Intl.DateTimeFormat {
let formatter = formatters.get(timeZone)
if (formatter === undefined) {
formatter = new Intl.DateTimeFormat('en-US', {
timeZone,
hourCycle: 'h23',
year: 'numeric',
month: '2-digit',
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
})
formatters.set(timeZone, formatter)
}
return formatter
}
/** What a wall clock in `timeZone` shows at `instant`, as a civil ISO string: "2026-10-01T10:00:00". */
export function toWallClock(instant: Date, timeZone: string): string {
const part: Record<string, string> = {}
for (const { type, value } of partsFormatter(timeZone).formatToParts(instant)) part[type] = value
return `${part.year}-${part.month}-${part.day}T${part.hour}:${part.minute}:${part.second}`
}
function offsetAt(ms: number, timeZone: string): number {
return Date.parse(`${toWallClock(new Date(ms), timeZone)}Z`) - ms
}
/**
* The instant at which a wall clock in `timeZone` shows `wall`. Times skipped or repeated by a
* daylight-saving change have no single answer: this picks a neighbouring instant, so validate
* them in your application if they matter.
*/
export function fromWallClock(wall: SuperScheduler.DateInput, timeZone: string): Date {
const asUtc = Date.parse(`${new SuperScheduler.Date(wall).value}Z`)
const guess = asUtc - offsetAt(asUtc, timeZone)
return new Date(asUtc - offsetAt(guess, timeZone))
}
/** API instants to scheduler events on the property's wall clock. */
export async function loadBookings(fromUtc: string, toUtc: string, timeZone: string) {
const rows = await fetchBookingInstants(fromUtc, toUtc)
return rows.map((row): SuperScheduler.EventData => ({
id: row.id,
resource: row.roomId,
text: row.guest,
start: toWallClock(new Date(row.startUtc), timeZone),
end: toWallClock(new Date(row.endUtc), timeZone),
}))
}
// Saving goes the other way: fromWallClock(event.start, 'Europe/Madrid').toISOString()Rechnen Sie auf dem Hinweg um (toWallClock, wenn Sie API-Zeilen auf Ereignisse abbilden) und auf dem Rückweg (fromWallClock, wenn Sie start und end speichern, die nach einem Ziehen SuperScheduler.Date-Objekte sind). Beim bereichsweisen Laden rechnen Sie start und end des Abschnitts, die in bürgerlicher Zeit vorliegen, auf dieselbe Weise um, bevor Sie eine UTC-basierte API abfragen.
Zeiten, die bei der Zeitumstellung übersprungen oder wiederholt werden, sind eine Geschäftsregel, kein Formatierungsdetail. Eine Buchung um 02:30 in der Nacht, in der die Uhren vorgestellt werden, existiert in Madrid nicht; entscheiden Sie, ob Sie sie ablehnen, verschieben oder anders speichern.
Wiederkehrende Ereignisse
Der Planer hat keine Engine für Wiederholungen. Die Felder recurrent und recurrentMasterId sind typisiert, aber control.events.findRecurrent() ist reserviert und gibt null zurück. Speichern Sie Serien in Ihrer Anwendung und expandieren Sie sie für die Tage auf dem Bildschirm zu gewöhnlichen Ereignissen. Geben Sie jedem Vorkommen eine ID, die über Anfragen hinweg stabil ist, etwa die Serien-ID plus das Datum, damit das bereichsweise Laden es zusammenführen kann:
import { SuperScheduler } from 'super-scheduler'
/** A weekly series as your application stores it. */
export interface WeeklySeries {
readonly id: string
readonly resource: string
readonly text: string
/** First occurrence, civil date-time with seconds. */
readonly start: string
readonly durationMinutes: number
/** 0 = Sunday ... 6 = Saturday. */
readonly weekdays: readonly number[]
/** Last day of the series, inclusive, as yyyy-MM-dd. */
readonly until: string
/** Days removed from the series, as yyyy-MM-dd. */
readonly exceptions: readonly string[]
}
/** The occurrences that overlap [from, to), each with an id that is stable across requests. */
export function expandWeekly(
series: WeeklySeries,
from: SuperScheduler.Date,
to: SuperScheduler.Date,
) {
const first = new SuperScheduler.Date(series.start)
const firstDay = first.getDatePart().ticks
const afterLastDay = new SuperScheduler.Date(series.until).addDays(1).ticks
// Look back far enough to catch an occurrence that started earlier and is still running.
const lookBack = Math.ceil(series.durationMinutes / 1440)
const events: SuperScheduler.EventData[] = []
for (
let day = from.getDatePart().addDays(-lookBack);
day.ticks < to.ticks;
day = day.addDays(1)
) {
if (day.ticks < firstDay || day.ticks >= afterLastDay) continue
if (!series.weekdays.includes(day.getDayOfWeek())) continue
const key = day.toString('yyyy-MM-dd')
if (series.exceptions.includes(key)) continue
const start = day.addTime(first.getTimePart())
const end = start.addMinutes(series.durationMinutes)
if (end.ticks <= from.ticks) continue
events.push({
id: `${series.id}:${key}`,
resource: series.resource,
text: series.text,
start,
end,
})
}
return events
}Auch das Bearbeiten liegt bei Ihnen. „Nur dieses Vorkommen“ bedeutet meist, das Datum zu den Ausnahmen der Serie hinzuzufügen und ein eigenständiges Ereignis anzulegen; „dieses und alle folgenden“ teilt die Serie; „alle Vorkommen“ ändert die Serie und expandiert sie neu. Bilden Sie Änderungen aus onEventsChange anhand der ID des Vorkommens auf diese Operationen ab. Das Expandieren in der load-Funktion eines Range-Loaders hält lange Serien günstig: Nur die sichtbaren Abschnitte werden expandiert.
Checkliste
- Eine einzige Konstante
LOCALE, übergeben an die Komponente und an jeden Aufruf vontoString. weekStartsundfirstDayOfWeek()stimmen überein.- Eigene Texte für Verlauf, Minimap, Badge und Statustexte für alle Sprachen außer Englisch und Spanisch.
- Start- und Endzeiten der Ereignisse als Strings in bürgerlicher Zeit mit Sekunden, in die Zeitzone des Geschäfts umgerechnet, bevor sie den Planer erreichen.
- Beim Speichern wird in Zeitpunkte zurückgerechnet, falls Ihr Backend solche speichert.
- Serien werden pro sichtbarem Zeitraum expandiert, mit stabilen IDs für die Vorkommen.
Planung einer VideoproduktionEin Dreh dauert länger. Verschieben Sie den abhängigen Schnitt, verstehen Sie warum, und nehmen Sie es zurück. Verwandte Anleitungen: Ressourcen, Ereignisse und Intervalle, Zeitskalen und Zoom, Tastatur, Barrierefreiheit und Touch und Daten nach Zeitraum laden.