Phase 3 (Kern): Laufzeitbibliothek, Bildschirm und Datei-E/A
Setzt den OpenSpec-Change phase-3-runtime-bildschirm um (77/77 Aufgaben). Abdeckung laut Inventar: 195 implementiert, 37 offen, 53 Non-Feature. Vollstaendigkeits-Inventar - docs/inventar.md mit 285 Eintraegen aus den Themenlisten von bas7advr.hlp und qb45advr.hlp, je mit Status und Fundstelle - crates/tb-frontend/tests/inventar.rs haelt die Tabelle in beide Richtungen gegen den Code; der Abdeckungsstand kann nicht veralten Bruchschritt (Puffer, Host, Korpus) - Cell/TextScreen ziehen ratatui-frei nach tb-runtime::screen; tb-ui behaelt Farbabbildung, Widget und den neuen Terminal-Host - Host wechselt vom Zeichenstrom auf Anzeige des Zellenpuffers plus Ereignisse (Taste, Groessenaenderung, Abbruch) - Korpusvergleich auf getrimmten Bildschirm-Snapshot; die acht bestehenden Sollausgaben blieben dabei unveraendert Groessenunabhaengigkeit - 80x25 ist nirgends mehr eine feste Grenze; Groessenaenderungen waehrend der Ausfuehrung werden zugestellt (Inhalt oben links erhalten, Cursor und VIEW PRINT geklemmt) - Korpusnachweis: dasselbe Programm bei 80x25 und 120x40 mit je eigener Sollausgabe, plus ein Programm mit Groessenwechsel mitten im Lauf Bibliothek - Breite Unicode-Zeichen belegen zwei Zellen (Cursor, POS, Randumbruch) - Bildschirm: CLS, COLOR, LOCATE, WIDTH, VIEW PRINT, SCREEN, CSRLIN, POS - Tastatur: INKEY$, INPUT$, Funktionstasten-Makros (KEY n / LIST / ON) - PRINT USING, LPRINT USING, FORMAT$, SetFormatCC - Mathematik mit kompatiblem PRNG (gleiche Saat, gleiche Folge) - Datum und Zeit mit Serienwerten ab 1899 - Finanzmathematik: FV#, PV#, Pmt#, IPmt#, PPmt#, NPer#, Rate#, NPV#, IRR#, MIRR#, SLN#, SYD#, DDB# - Datei-E/A: sequenziell, RANDOM (Recordpuffer und UDT-Variablen), BINARY, FIELD/LSET/RSET, Statusfunktionen, Dateisystem, MK$/CV - System: ENVIRON, FRE, CLEAR, TRON/TROFF, STACK, ERDEV, ERR-Anweisung Altlasten aus Phase 2 - ON ERROR GOTO auf Modulebene ist aus Prozeduren ansprechbar (prozeduruebergreifender Fixup im Codegenerator) - DATA behaelt seinen Rohtext (Gross-/Kleinschreibung, innerer Leerraum) - Die vier TODO-verify-Zellen der Konvertierungsmatrix sind aufgeloest Vom Inventar aufgedeckte Fehler - Zwoelf Non-Features wies der Compiler entgegen der Phase-1-Spec nicht ab (CALLS, SSEG, POINT, VIEW, COM, PEN, STRIG, STICK, die String*-Routinen, LINE und OPEN "COMn:") -- geschlossen - Drei Gruppen fehlten im urspruenglichen Umfang: Finanzmathematik, Record-Konvertierung, Rest der Dateisystemfunktionen - bas7advr.hlp allein ist keine vollstaendige Quelle; das Inventar bildet die Vereinigung mit qb45advr.hlp Neue Changes - phase-3-isam: schliesst Phase 3 ab (Speicherschicht redb) - phase-3-ortszeit: zieht die UTC-Abweichung zurueck Neue Abhaengigkeit: unicode-width. Dokumentiert: sprachreferenz.md und tbvm-design.md sind TODO-frei, docs/bibliothek.md neu, PLAN.md fortgeschrieben. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
2
openspec/changes/phase-3-ortszeit/.openspec.yaml
Normal file
2
openspec/changes/phase-3-ortszeit/.openspec.yaml
Normal file
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-09-04
|
||||
180
openspec/changes/phase-3-ortszeit/design.md
Normal file
180
openspec/changes/phase-3-ortszeit/design.md
Normal file
@@ -0,0 +1,180 @@
|
||||
## Context
|
||||
|
||||
Siehe proposal.md — Why. Der Ist-Zustand ist eng umrissen:
|
||||
|
||||
- `tb-runtime::datetime` rechnet vollständig selbst: Kalenderumrechnung
|
||||
(Howard Hinnant), serielle Datumswerte ab dem 30.12.1899, `WEEKDAY`,
|
||||
Textformen. Diese Rechnung ist getestet und bleibt.
|
||||
- Der einzige Punkt, an dem die Zeitzone eine Rolle spielt, ist
|
||||
`jetzt_sekunden()` — Sekunden seit der Unix-Epoche. Alles Weitere
|
||||
(`jetzt_serial`, `DATE$`, `TIME$`, `TIMER`, `NOW`) baut darauf auf.
|
||||
- `tb-runtime` hat bislang eine einzige Abhängigkeit mit fachlichem
|
||||
Gewicht: `unicode-width`.
|
||||
|
||||
Damit ist die Aufgabe klein: **eine Zahl** — der UTC-Versatz zu einem
|
||||
Zeitpunkt — kommt künftig von außen.
|
||||
|
||||
## Goals / Non-Goals
|
||||
|
||||
**Goals:**
|
||||
|
||||
- Zeitfunktionen liefern das, was die Uhr des Rechners zeigt.
|
||||
- Sommerzeit wird zum jeweiligen Zeitpunkt berücksichtigt.
|
||||
- Die Berührungsfläche zur Bibliothek bleibt eine Funktion, damit sie
|
||||
austauschbar ist und die getestete Kalenderrechnung unberührt bleibt.
|
||||
- Zeitverhalten bleibt automatisiert prüfbar, ohne von der Zone des
|
||||
Testrechners abzuhängen.
|
||||
|
||||
**Non-Goals:**
|
||||
|
||||
- Zeitzonenbehaftete Datentypen im Dialekt — das Vorbild kennt nur
|
||||
Wanduhrzeit.
|
||||
- Eine Sprachanbindung an die Bibliothek (Zonennamen, Umrechnung zwischen
|
||||
Zonen). Das ist der Stufe-2-Eintrag im PLAN, nicht dieser Change.
|
||||
- Historische Zonendaten jenseits dessen, was die Systemdatenbank
|
||||
hergibt.
|
||||
|
||||
## Decisions
|
||||
|
||||
### D1: `jiff` als Zeitzonenbibliothek
|
||||
|
||||
*Gewählt:* `jiff` — sie liest die Zeitzonendatenbank des Systems und
|
||||
liefert den Versatz zu einem Zeitpunkt ohne Einschränkung.
|
||||
|
||||
*Alternativen:*
|
||||
|
||||
| Bibliothek | Bewertung |
|
||||
|---|---|
|
||||
| `jiff` | Für genau diese Frage gebaut; Systemzonendatenbank; keine Sicherheitsauflage. **Gewählt.** |
|
||||
| `chrono` (≥ 0.4.20) | Gleichwertig sicher, seit 0.4.20 ohne `localtime_r` (Zonenermittlung über `iana-time-zone`, Datenbank über einen `tz-rs`-Zweig). Etablierter, bringt aber Serde-/Ökosystem-Anbindung mit, die hier niemand braucht. Tragfähige zweite Wahl. |
|
||||
| `time` | Der lokale Versatz ist auf Unix nur nach ausdrücklichem Opt-in in möglicherweise undefiniertes Verhalten verfügbar (`set_soundness`). **Verworfen** — das ist kein Preis für eine Uhrzeit. |
|
||||
| Eigenbau (`iana-time-zone` + TZif-Parser) | Hieße, die Zonendatenbank selbst zu lesen und dauerhaft nachzupflegen. Genau das, wofür man eine Bibliothek nimmt. **Verworfen.** |
|
||||
|
||||
*Warum die Wahl leicht revidierbar bleibt:* Die Bibliothek wird an genau
|
||||
einer Stelle aufgerufen (D2). Ein Wechsel zu `chrono` wäre ein Austausch
|
||||
dieser einen Funktion.
|
||||
|
||||
### D2: Berührungsfläche ist eine Funktion
|
||||
|
||||
```
|
||||
tb-runtime::datetime
|
||||
|
||||
utc_versatz(zeitpunkt: i64) -> Option<i32> // Sekunden, None = Zone unbekannt
|
||||
└── einziger Aufruf der Bibliothek
|
||||
|
||||
jetzt_sekunden() ─┐
|
||||
jetzt_serial() ├── rechnen weiter selbst
|
||||
civil_from_days() │
|
||||
weekday() … ─┘
|
||||
```
|
||||
|
||||
Die Kalenderrechnung sieht die Bibliothek nie. Sie bekommt nach wie vor
|
||||
Sekunden seit der Epoche — nur eben um den Versatz verschobene.
|
||||
|
||||
*Warum nicht die Bibliothek durchreichen:* Ihre Datums-/Zeittypen wären
|
||||
ein zweites Kalendermodell neben dem des Dialekts (der bei 1899 zählt,
|
||||
`WEEKDAY` = 1 für Sonntag, CURRENCY-nahe Serienwerte). Zwei Modelle
|
||||
nebeneinander wären eine dauerhafte Fehlerquelle; die vorhandene Rechnung
|
||||
ist getestet und bleibt maßgeblich.
|
||||
|
||||
### D3: Der Versatz gilt je Zeitpunkt, nicht je Programmlauf
|
||||
|
||||
`utc_versatz` bekommt den Zeitpunkt als Argument. Ein Programm, das über
|
||||
eine Zeitumstellung hinweg läuft, folgt ihr; ein Programm, das mit
|
||||
`DATE$ =` in einen anderen Teil des Jahres springt, bekommt den dort
|
||||
gültigen Versatz.
|
||||
|
||||
*Preis:* Eine Zonenabfrage je Zeitabfrage. Bei den Aufrufmengen eines
|
||||
Terminalprogramms belanglos; die Bibliothek hält die Zonendaten selbst
|
||||
vor.
|
||||
|
||||
### D4: Zonenquelle ist umschaltbar — damit Tests nicht von der Maschine abhängen
|
||||
|
||||
```rust
|
||||
pub enum Zeitzone {
|
||||
/// Zone des Rechners (Vorgabe).
|
||||
System,
|
||||
/// Fester Versatz in Sekunden — für Tests und den Korpus.
|
||||
Fest(i32),
|
||||
/// Zone nicht ermittelbar; es gilt UTC.
|
||||
Unbekannt,
|
||||
}
|
||||
```
|
||||
|
||||
`RtState` hält eine `Zeitzone`. Die Vorgabe ist `System`; schlägt die
|
||||
Ermittlung fehl, wird daraus `Unbekannt`. Tests und Korpusprogramme
|
||||
setzen `Fest(n)`.
|
||||
|
||||
*Warum nicht `TZ` in den Tests setzen:* Umgebungsvariablen sind
|
||||
prozessweit, Tests laufen nebenläufig, und `set_var` ist seit Rust 2024
|
||||
`unsafe`. Ein Zustand im `RtState` ist der offensichtliche Weg — er ist
|
||||
genau so weit sichtbar wie nötig.
|
||||
|
||||
*Korpus:* Das Harness bekommt eine Kopfzeilen-Direktive analog zu
|
||||
`' tb-screen:` und `' tb-tempdir`:
|
||||
|
||||
```text
|
||||
' tb-tz: +02:00
|
||||
```
|
||||
|
||||
Damit bleibt die Sollausgabe eines Zeitprogramms unabhängig davon, wo der
|
||||
Testrechner steht.
|
||||
|
||||
### D5: Rückfallebene ist sichtbar, nicht still
|
||||
|
||||
Ohne ermittelbare Zone gilt UTC — ein Abbruch wäre unverhältnismäßig, ein
|
||||
stiller Wechsel aber ein Verstoß gegen den Guiding Principle. Die Laufzeit
|
||||
führt den Zustand mit, und der Zustand ist abfragbar; die Sprachreferenz
|
||||
beschreibt ihn.
|
||||
|
||||
*Wie ein Programm es erfährt:* Über die vorhandene Systemabfrage
|
||||
`ENVIRON$` wäre es geraten. Stattdessen bekommt die Laufzeit einen
|
||||
benannten Zustand, den der Runner beim Start auf die Fehlerausgabe
|
||||
schreibt, wenn er `Unbekannt` ist — einmal, nicht je Abfrage. Ein
|
||||
Programm, das es programmatisch braucht, bekommt es in Stufe 2 über die
|
||||
Bibliotheksanbindung.
|
||||
|
||||
### D6: Reihenfolge der Umsetzung
|
||||
|
||||
```
|
||||
1. Abhaengigkeit + utc_versatz() -> isoliert testbar
|
||||
2. jetzt_sekunden/jetzt_serial umstellen -> DATE$/TIME$/TIMER/NOW folgen
|
||||
3. Zeitzone im RtState + Korpusdirektive -> Tests werden maschinenunabhaengig
|
||||
4. Doku: Abweichung zurueckziehen, PLAN Stufe 2
|
||||
```
|
||||
|
||||
## Risks / Trade-offs
|
||||
|
||||
- **Erste schwere Abhängigkeit der Laufzeit** → bewusst entschieden
|
||||
(2026-09-04). Die Berührungsfläche ist eine Funktion (D2); ein Wechsel
|
||||
der Bibliothek bleibt ein lokaler Eingriff.
|
||||
- **Zeitabhängige Tests werden flatterig** → deshalb D4: kein Test und
|
||||
kein Korpusprogramm fragt die echte Zone ab. Was die Systemzone
|
||||
betrifft, wird über `Fest(n)` und `Unbekannt` geprüft.
|
||||
- **Zeitumstellung erzeugt mehrdeutige Wanduhrzeiten** (Rückstellung) und
|
||||
nicht existierende (Vorstellung) → betrifft nur die Richtung
|
||||
Wanduhr → Zeitpunkt. Die Zeitfunktionen dieses Dialekts gehen die
|
||||
andere Richtung (Zeitpunkt → Wanduhr) und sind davon nicht betroffen.
|
||||
`DATEVALUE`/`TIMEVALUE` lesen Wanduhrzeit und rechnen gar nicht um.
|
||||
`DATE$ =`/`TIME$ =` setzen einen Versatz gegen die aktuelle Wanduhrzeit
|
||||
— auch das ist eindeutig.
|
||||
- **Die Systemzonendatenbank kann fehlen** (schlanke Container) → D5.
|
||||
- **Bauzeit und Binärgröße wachsen** → für ein Werkzeug, dessen Programme
|
||||
Uhrzeiten anzeigen, ist eine falsche Uhrzeit der größere Preis.
|
||||
|
||||
## Migration Plan
|
||||
|
||||
Rein verhaltensändernd, ohne Formatbruch: `.tbc`-Dateien, Korpus-Golden-
|
||||
Files und Schnittstellen bleiben unberührt. Das einzige beobachtbare
|
||||
Verhalten, das sich ändert, ist der Wert von `DATE$`, `TIME$`, `TIMER`
|
||||
und `NOW` — und zwar zum Richtigen hin.
|
||||
|
||||
Rücknahme: Ein Zurücksetzen auf UTC wäre `Zeitzone::Unbekannt` als
|
||||
Vorgabe; die Abhängigkeit bliebe ungenutzt.
|
||||
|
||||
## Open Questions
|
||||
|
||||
- Ob die Bibliotheksanbindung in Stufe 2 (Zonennamen, Umrechnung zwischen
|
||||
Zonen als BASIC-Funktionen) auf derselben Bibliothek aufsetzt oder eine
|
||||
eigene Wahl trifft, entscheidet Stufe 2. Für diesen Change ohne
|
||||
Wirkung — hier wird nur der Versatz gebraucht.
|
||||
76
openspec/changes/phase-3-ortszeit/proposal.md
Normal file
76
openspec/changes/phase-3-ortszeit/proposal.md
Normal file
@@ -0,0 +1,76 @@
|
||||
# Ortszeit statt UTC
|
||||
|
||||
## Why
|
||||
|
||||
`DATE$`, `TIME$`, `TIMER` und `NOW` liefern heute koordinierte Weltzeit.
|
||||
Das ist keine Rekonstruktion des Vorbilds, sondern eine Notlösung: die
|
||||
Standardbibliothek von Rust kennt keine Zeitzonen, und in
|
||||
`phase-3-runtime-bildschirm` sollte die erste schwere Abhängigkeit der
|
||||
Laufzeit nicht nebenbei entstehen. Die Abweichung steht in
|
||||
docs/sprachreferenz.md.
|
||||
|
||||
Für ein BASIC zum Bauen von Terminal-Werkzeugen ist das ein echter
|
||||
Mangel: Ein Programm, das eine Uhr anzeigt, ein Protokoll schreibt oder
|
||||
einen Termin prüft, zeigt schlicht die falsche Zeit — je nach Zone um
|
||||
Stunden daneben. Das Vorbild lief auf der Ortszeit des Rechners; jedes
|
||||
übernommene Programm rechnet damit.
|
||||
|
||||
Der Projektinhaber hat am 2026-09-04 entschieden, dafür eine Bibliothek
|
||||
in die Laufzeit aufzunehmen. Dieser Change zieht die Abweichung zurück.
|
||||
|
||||
## What Changes
|
||||
|
||||
- **Zeitfunktionen liefern Ortszeit**: `DATE$`, `TIME$`, `TIMER` und
|
||||
`NOW` rechnen in der Zeitzone des Rechners statt in UTC. `TIMER` zählt
|
||||
Sekunden seit der **lokalen** Mitternacht.
|
||||
- **Sommerzeit wird berücksichtigt**: Der Versatz wird für den jeweiligen
|
||||
Zeitpunkt bestimmt, nicht einmalig beim Programmstart — ein Programm,
|
||||
das über einen Zeitumstellungspunkt hinweg läuft, folgt ihm.
|
||||
- **Neue Abhängigkeit in `tb-runtime`**: eine Zeitzonenbibliothek, deren
|
||||
Berührungsfläche bewusst auf eine einzige Frage beschränkt bleibt —
|
||||
„welcher UTC-Versatz gilt zu diesem Zeitpunkt?". Die Kalenderrechnung
|
||||
(serielle Datumswerte, `WEEKDAY`, Zerlegung) bleibt die vorhandene,
|
||||
getestete Eigenimplementierung in `tb-runtime::datetime`.
|
||||
- **Rückfallebene**: Lässt sich die Zeitzone des Rechners nicht
|
||||
ermitteln, gilt UTC. Das Programm läuft weiter; die Rückfallebene ist
|
||||
über eine Funktion der Laufzeit erkennbar und dokumentiert.
|
||||
- **`DATE$ =` / `TIME$ =` bleiben ein Programmversatz** (sie stellen
|
||||
nicht die Systemuhr) — sie wirken künftig auf die Ortszeit.
|
||||
- **Abweichung zurückziehen**: Der Eintrag „Uhr läuft in UTC" entfällt
|
||||
aus docs/sprachreferenz.md; an seine Stelle tritt die Beschreibung der
|
||||
Zonenermittlung samt Rückfallebene.
|
||||
- **Stufe 2 im PLAN**: Die Zeitzonenbibliothek wird in den Ideenspeicher
|
||||
„Runtime-Bibliotheken als BASIC-Bibliotheken" aufgenommen — neben
|
||||
crossterm —, damit BASIC-Programme später direkt auf Zonen zugreifen
|
||||
können (Zonennamen, Versatz zu einem Zeitpunkt, Umrechnung zwischen
|
||||
Zonen).
|
||||
|
||||
**Non-Goals:** Zeitzonenbehaftete Datentypen im Dialekt (das Vorbild
|
||||
kennt nur lokale Wanduhrzeit); eine Sprachanbindung an die Bibliothek
|
||||
(das ist der Stufe-2-Eintrag, nicht dieser Change); Änderungen an der
|
||||
Zählweise serieller Datumswerte oder an `DATEVALUE`/`TIMEVALUE`, die
|
||||
Wanduhrzeit lesen und daher keine Umrechnung brauchen.
|
||||
|
||||
## Capabilities
|
||||
|
||||
### Modified Capabilities
|
||||
|
||||
- `konsolen-basisbibliothek`: Die Datums- und Zeitfunktionen SHALL die
|
||||
Ortszeit des Rechners liefern statt UTC, einschließlich Sommerzeit und
|
||||
einer dokumentierten Rückfallebene.
|
||||
|
||||
## Impact
|
||||
|
||||
- `crates/tb-runtime/src/datetime.rs`: Versatzermittlung über die neue
|
||||
Bibliothek; `jetzt_serial`/`jetzt_sekunden` liefern Ortszeit. Die
|
||||
Kalenderrechnung bleibt unverändert.
|
||||
- `crates/tb-runtime/src/builtins.rs`: `DATE$`, `TIME$`, `TIMER`, `NOW`
|
||||
rechnen über die neue Funktion.
|
||||
- `Cargo.toml` (Workspace) und `crates/tb-runtime/Cargo.toml`: neue
|
||||
Abhängigkeit.
|
||||
- `tests/compat`: Korpusprogramm für die Zeitfunktionen, das ohne
|
||||
Abhängigkeit von der Zone des Testrechners prüfbar bleibt.
|
||||
- `docs/sprachreferenz.md`: Abweichung „Uhr läuft in UTC" entfällt;
|
||||
Zonenermittlung und Rückfallebene beschrieben.
|
||||
- `docs/bibliothek.md`: Abschnitt Datum/Zeit fortgeschrieben.
|
||||
- `PLAN.md`: Stufe-2-Eintrag um die Bibliothek erweitert.
|
||||
@@ -0,0 +1,58 @@
|
||||
## ADDED Requirements
|
||||
|
||||
### Requirement: Zeitfunktionen liefern Ortszeit
|
||||
`DATE$`, `TIME$`, `TIMER` und `NOW` SHALL den Zeitpunkt in der Zeitzone
|
||||
des Rechners liefern, nicht in koordinierter Weltzeit. `TIMER` SHALL die
|
||||
Sekunden seit der **lokalen** Mitternacht zählen. Der maßgebliche Versatz
|
||||
SHALL für den jeweils abgefragten Zeitpunkt bestimmt werden, nicht einmal
|
||||
beim Programmstart — ein Programm, das über eine Zeitumstellung hinweg
|
||||
läuft, folgt ihr. Die Zerlegungsfunktionen (`DAY`, `MONTH`, `YEAR`,
|
||||
`WEEKDAY`, `HOUR`, `MINUTE`, `SECOND`) arbeiten unverändert auf seriellen
|
||||
Werten und rechnen selbst nicht um.
|
||||
|
||||
#### Scenario: Datum und Uhrzeit stimmen mit der Systemuhr überein
|
||||
- **WHEN** ein Programm `DATE$` und `TIME$` abfragt
|
||||
- **THEN** entsprechen sie der Ortszeit des Rechners zum Abfragezeitpunkt
|
||||
|
||||
#### Scenario: TIMER zählt ab lokaler Mitternacht
|
||||
- **WHEN** `TIMER` abgefragt wird
|
||||
- **THEN** entspricht der Wert den Sekunden seit der letzten lokalen Mitternacht, nicht seit der UTC-Mitternacht
|
||||
|
||||
#### Scenario: NOW und die Zerlegungsfunktionen passen zusammen
|
||||
- **WHEN** `n# = NOW` gebildet und `HOUR(n#)` ausgewertet wird
|
||||
- **THEN** liefert `HOUR(n#)` dieselbe Stunde, die auch `TIME$` nennt
|
||||
|
||||
#### Scenario: Sommerzeit wirkt zum jeweiligen Zeitpunkt
|
||||
- **WHEN** in einer Zone mit Sommerzeit ein Zeitpunkt vor und einer nach der Umstellung abgefragt wird
|
||||
- **THEN** unterscheiden sich die beiden Versätze um die Umstellungsspanne
|
||||
|
||||
### Requirement: Zonenermittlung mit Rückfallebene
|
||||
Die Laufzeit SHALL die Zeitzone des Rechners über die
|
||||
Betriebssystemeinstellung bestimmen. Lässt sie sich nicht ermitteln,
|
||||
SHALL UTC gelten und das Programm ohne Fehler weiterlaufen. Ob die
|
||||
Rückfallebene greift, MUST für ein Programm erkennbar sein und in
|
||||
docs/sprachreferenz.md beschrieben stehen; ein stiller Wechsel auf UTC
|
||||
MUST NOT vorkommen.
|
||||
|
||||
#### Scenario: Zone nicht ermittelbar
|
||||
- **WHEN** die Zeitzone des Rechners nicht bestimmt werden kann
|
||||
- **THEN** rechnen die Zeitfunktionen in UTC und das Programm läuft ohne Fehler weiter
|
||||
|
||||
#### Scenario: Rückfallebene ist erkennbar
|
||||
- **WHEN** ein Programm den Zonenzustand abfragt
|
||||
- **THEN** unterscheidet die Antwort erkennbar zwischen ermittelter Zone und Rückfall auf UTC
|
||||
|
||||
### Requirement: Programmversatz wirkt auf die Ortszeit
|
||||
`DATE$ = text$` und `TIME$ = text$` SHALL weiterhin nicht die Systemuhr
|
||||
stellen, sondern einen programmeigenen Versatz setzen. Dieser Versatz
|
||||
SHALL auf die **Ortszeit** wirken: nach `TIME$ = "10:20:30"` nennt
|
||||
`TIME$` diese Uhrzeit, und `NOW`, `HOUR` und `TIMER` stimmen damit
|
||||
überein.
|
||||
|
||||
#### Scenario: Gesetzte Uhrzeit wird zurückgelesen
|
||||
- **WHEN** `TIME$ = "10:20:30"` ausgeführt und danach `TIME$` abgefragt wird
|
||||
- **THEN** nennt `TIME$` `10:20:30`
|
||||
|
||||
#### Scenario: Versatz wirkt auf alle Zeitfunktionen
|
||||
- **WHEN** `DATE$ = "01-02-1993"` gesetzt und danach `YEAR(NOW)` ausgewertet wird
|
||||
- **THEN** liefert `YEAR(NOW)` 1993
|
||||
35
openspec/changes/phase-3-ortszeit/tasks.md
Normal file
35
openspec/changes/phase-3-ortszeit/tasks.md
Normal file
@@ -0,0 +1,35 @@
|
||||
## 1. Versatzermittlung
|
||||
|
||||
- [ ] 1.1 `jiff` als Workspace-Abhängigkeit aufnehmen und in `tb-runtime` einbinden; verifiziert dadurch, dass `cargo build -p tb-runtime` durchläuft und `cargo tree -p tb-runtime` die Bibliothek genau einmal zeigt
|
||||
- [ ] 1.2 `datetime::utc_versatz(zeitpunkt: i64) -> Option<i32>` als einzigen Aufrufpunkt der Bibliothek schreiben (Sekunden Versatz, `None` = Zone nicht ermittelbar); verifiziert durch Unit-Test, dass der Versatz für einen festen Zeitpunkt im gültigen Bereich −50400…50400 liegt
|
||||
- [ ] 1.3 Sommerzeit prüfen: für dieselbe Zone einen Zeitpunkt im Januar und einen im Juli abfragen; verifiziert durch Unit-Test, dass sich die Versätze in einer Zone mit Sommerzeit unterscheiden und in einer ohne gleich bleiben
|
||||
- [ ] 1.4 Sicherstellen, dass die Kalenderrechnung unberührt bleibt; verifiziert dadurch, dass `datetime.rs` außerhalb von `utc_versatz` keinen Bibliotheksaufruf enthält und die bestehenden `datetime`-Tests unverändert grün sind
|
||||
|
||||
## 2. Zonenzustand in der Laufzeit
|
||||
|
||||
- [ ] 2.1 `Zeitzone { System, Fest(i32), Unbekannt }` einführen und in `RtState` halten; Vorgabe `System`, bei fehlgeschlagener Ermittlung `Unbekannt`; verifiziert durch Unit-Test je Variante
|
||||
- [ ] 2.2 `jetzt_sekunden`/`jetzt_serial` auf den Zonenzustand umstellen; verifiziert durch Unit-Test, dass `Fest(3600)` genau eine Stunde gegenüber `Unbekannt` verschiebt
|
||||
- [ ] 2.3 `DATE$`, `TIME$`, `TIMER` und `NOW` über den Zonenzustand rechnen; verifiziert durch Test, dass `HOUR(NOW)` und die Stunde aus `TIME$` bei `Fest(n)` übereinstimmen
|
||||
- [ ] 2.4 `TIMER` zählt ab lokaler Mitternacht; verifiziert durch Test, dass sich `TIMER` bei `Fest(3600)` gegenüber `Unbekannt` um 3600 verschiebt (modulo Tageslänge)
|
||||
- [ ] 2.5 `DATE$ =` / `TIME$ =` wirken auf die Ortszeit; verifiziert durch Test, dass `TIME$` nach `TIME$ = "10:20:30"` genau diesen Wert nennt und `HOUR(NOW)` 10 liefert
|
||||
|
||||
## 3. Rückfallebene
|
||||
|
||||
- [ ] 3.1 Bei nicht ermittelbarer Zone auf UTC zurückfallen, ohne Fehler; verifiziert durch Test mit `Zeitzone::Unbekannt`, dass alle Zeitfunktionen Werte liefern
|
||||
- [ ] 3.2 Den Rückfall beim Programmstart einmalig auf die Fehlerausgabe melden (nicht je Abfrage); verifiziert dadurch, dass `tbc run` bei `Unbekannt` genau eine Meldung schreibt und die Standardausgabe unberührt bleibt
|
||||
- [ ] 3.3 Rückfallebene in docs/sprachreferenz.md beschreiben; verifiziert durch den Abschnittseintrag
|
||||
|
||||
## 4. Prüfbarkeit ohne Abhängigkeit von der Testmaschine
|
||||
|
||||
- [ ] 4.1 Kopfzeilen-Direktive `' tb-tz: ±HH:MM` im Korpus-Harness auswerten und als `Zeitzone::Fest` setzen; verifiziert dadurch, dass ein Korpusprogramm ohne die Direktive weiterhin läuft und eines mit ihr den gesetzten Versatz verwendet
|
||||
- [ ] 4.2 Korpusprogramm `zeitzone.bas` mit festem Versatz: `DATE$`/`TIME$`/`TIMER`/`NOW` gegen eine per `DATE$ =`/`TIME$ =` gesetzte Uhrzeit prüfen; verifiziert dadurch, dass die Sollausgabe unabhängig von der Zone des Testrechners stimmt
|
||||
- [ ] 4.3 Bestehendes `datumzeit.bas` auf die Direktive umstellen, damit es auch nach der Umstellung deterministisch bleibt; verifiziert dadurch, dass seine Sollausgabe unverändert bleibt
|
||||
|
||||
## 5. Abschluss
|
||||
|
||||
- [ ] 5.1 Abweichung „Uhr läuft in UTC" aus docs/sprachreferenz.md entfernen und durch die Beschreibung der Zonenermittlung ersetzen; verifiziert dadurch, dass der Abweichungspunkt nicht mehr auftaucht
|
||||
- [ ] 5.2 `docs/bibliothek.md`, Abschnitt Datum/Zeit, fortschreiben; verifiziert durch den geänderten Abschnitt
|
||||
- [ ] 5.3 PLAN.md Stufe 2, Eintrag „Runtime-Bibliotheken als BASIC-Bibliotheken", um die Zeitzonenbibliothek erweitern (Zonennamen, Versatz zu einem Zeitpunkt, Umrechnung zwischen Zonen) — neben crossterm; verifiziert durch den ergänzten Eintrag
|
||||
- [ ] 5.4 PLAN.md Phase 3: den Hinweis auf die UTC-Abweichung durch den Verweis auf diesen Change ersetzen; verifiziert durch den aktualisierten Abschnitt
|
||||
- [ ] 5.5 Inventar unverändert lassen und den Abgleichstest prüfen; verifiziert dadurch, dass `cargo test -p tb-frontend --test inventar` grün bleibt (die Elemente waren bereits implementiert, nur ihr Zeitbezug ändert sich)
|
||||
- [ ] 5.6 Vollständige Suite ausführen; verifiziert dadurch, dass `cargo test --workspace` grün ist
|
||||
Reference in New Issue
Block a user