Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
aa25d3c
Exchange zone definitions: read them and compute a midnight from them…
Timtam Oct 10, 2026
83c63b2
All-day items read their day in each boundary's own zone (233, 236, 239)
Timtam Oct 10, 2026
b66e3fb
Merge remote-tracking branch 'origin/main' into feat/ews-writer-47a-date
Timtam Oct 10, 2026
653e37d
Exchange writer: a series starts on its first day, an all-day day on …
Timtam Oct 10, 2026
142604e
Tests for the Exchange writer, and the day-zone-unreadable sentence o…
Timtam Oct 10, 2026
0b14b84
Docs for PR 8a: the first-day rule, 47a on the stored zones, zone def…
Timtam Oct 10, 2026
cda0874
Two more tests for PR 8a: a zoned series' rule-only edit, a custom-zo…
Timtam Oct 10, 2026
93456d9
First check of #121: a flipped all-day flag, Windows' new-year marker…
Timtam Oct 10, 2026
cbfae15
Second check of #121: a withheld day without the copy, definitions fo…
Timtam Oct 10, 2026
02e46df
Third check of #121: a blind series update's first day, sign-in and g…
Timtam Oct 10, 2026
fbd2591
Fourth check of #121: the log says what was sent, decision 233's wiri…
Timtam Oct 10, 2026
bea6fc0
Fifth check of #121: the blind-write log after the empty check, ews.m…
Timtam Oct 10, 2026
9b05c11
Sixth check of #121: the written zone looked up once, the round 3 gen…
Timtam Oct 10, 2026
ca398e0
Seventh check of #121: zone ids decoded, so an id holding '&' matches…
Timtam Oct 10, 2026
8401281
Live round 6 of #121: record what Exchange did
Timtam Oct 10, 2026
31fdd7a
Review of the live results of #121: what step 9 measured, and its name
Timtam Oct 10, 2026
269ce30
Second review of the live results of #121: step 9 does not show the o…
Timtam Oct 10, 2026
d63bbe5
Third review of the live results of #121: the EndDate comments name t…
Timtam Oct 10, 2026
05afb18
Fourth review of the live results of #121: 234 back on the unchecked …
Timtam Oct 10, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 91 additions & 12 deletions DESIGN-series-time-zone.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,11 +121,16 @@ keinen, dort ist die Wahl Tonis Sache.
deshalb nur diesen Schutz. Die Regel steht einmal im Kern, und die Adapter
fragen sie. Lesefehler, Update-Regel und Datumsfehler werden eigene Stufen
nach der dritten Runde.
- **47a — Änderungen behalten die gespeicherte Zone.** Ändert Aperio einen
ganztägigen Exchange-Termin, der schon eine Zone trägt, etwa aus Outlook,
gehen Beginn und Ende auf Mitternacht in dieser Zone. Die Zone selbst bleibt
unberührt. Das passt zu 18a und dazu, dass Unberührtes wörtlich bleibt. Die
dritte Runde bestätigt es vor dem Bau.
- **47a — Änderungen behalten die gespeicherte Zone.** *(gebaut, PR 8a)*
Ändert Aperio einen ganztägigen Exchange-Termin, der schon eine Zone trägt,
etwa aus Outlook, gehen Beginn und Ende auf Mitternacht in dieser Zone. Die
Zone selbst bleibt unberührt. Das passt zu 18a und dazu, dass Unberührtes
wörtlich bleibt. Die dritte Runde hat es bestätigt (R3-1, R3-3, R3-7b). Mit
PR 8a kam dazu: jede Grenze in ihrer eigenen gespeicherten Zone (233), auch
in einer Zone, deren Kennung tzdatas eigener Name ist (236), oder einer, die
Exchange vollständig definiert (232, 239); eine Ausnahme in den Zonen ihrer
Serie; ist eine Zone nicht lesbar, wird der Tag nicht geschrieben und die
Person hört den Satz aus 237. Der Titel geht trotzdem durch.
- **48a — ganztägige Serien wiederholen sich an Kalendertagen.** *(gebaut)*
Aperio wiederholte ganztägige Serien in UTC. Östlich von UTC landete ein
genannter Wochentag deshalb einen Tag zu spät, bei jedem Anbieter außer
Expand Down Expand Up @@ -635,9 +640,18 @@ der Serie (21a), der Rest behält die Zone der ganzen Serie.
„Exchange kann die Zeitzone {Stadt} nicht speichern; die Serie steht auf
UTC.“ Kopieren oder Verschieben nach Exchange wird mit der Zone im Grund
abgelehnt.
- **Exchange und Microsoft 365** leiten Start- und Enddatum und die Standard-Tage
heute aus dem UTC-Datum ab. Beide müssen sie auf der Uhr der Serie lesen, bevor
die Editoren Beginn und UNTIL auf diese Uhr stellen.
- **Exchange** liest seit PR 8a den ersten Tag einer Serie auf der Uhr, auf der
Exchange sie wiederholt (`rule_first_day`): ganztägig der Tag des Geräts,
beim Anlegen die geschriebene Zone, beim Ändern die gespeicherte Startzone
(234), ohne lesbaren Serverstand die Zone, die die Änderung mitschreibt,
sonst UTC. Wechselt ein Ändern dabei die Zone, wandert der Termin trotzdem:
Der Live-Test 8a hat gemessen, dass ein Einzeltermin, der so zur Serie
wird, um den Versatz wandert, weil die neue Zone ohne Beginn und Ende die
gespeicherte Uhrzeit behält. Der nächste PR schreibt deshalb die Zone, dann
Beginn und Ende (auch unverändert), dann die Regel am Tag der neuen Zone;
das löst 234 ab. **Microsoft 365** leitet Start- und Enddatum und die
Standard-Tage weiter aus dem UTC-Datum ab und muss sie auf der Uhr der Serie
lesen, bevor die Editoren Beginn und UNTIL auf diese Uhr stellen.
- **Handy-Kalender** speichern keine Regel; die Auswahl ist dort nicht da.

### Nach dem Speichern
Expand Down Expand Up @@ -879,8 +893,60 @@ Handy im selben PR.
- Aperio zeigt eine Ausnahme unter dem Betreff der Serie, nicht unter ihrem
eigenen. Die verschobene Ausnahme steht richtig nur am Dienstag.
- Aperio zeigt die beschädigte Serie einen Tag zu spät (Lesefehler, 48a).

Live-Test 8a (10. Oktober 2026, derselbe Server). Toni hat die Schritte 1
bis 5 mit einem Desktop-Build von PR 8a von Hand gemacht und in Outlook
nachgesehen. Die Schritte 6 bis 9 hat ein Testprogramm außerhalb des
Repositorys über Aperios eigenen Adapter gemacht; es hat seine Termine
selbst per EWS angelegt und zurückgelesen, was Exchange speichert und was
die Kalenderansicht zeigt. Gemeint war jeweils November 2026:
- Eine neue ganztägige Serie (täglich, 4 Mal, ab Montag, dem 2.) steht vom
2. bis zum 5., eine zweiwöchentliche am 2., 16. und 30. Eine Serie mit
Uhrzeit um 00:30 ohne gewählten Wochentag steht montags. Der Datumsfehler
ist damit behoben. Eine ganztägige Serie ohne Zone zeigt Outlook mit der
Zone „(UTC+00:00) Monrovia, Reykjavik“, also Greenwich (43b).
- Ein ganztägiger Outlook-Termin, von Montag auf Dienstag verschoben, und
eine Ausnahme einer Outlook-Serie liegen danach einen Tag am neuen Tag
(47a). Eine reine Regeländerung lässt eine Outlook-Serie auf ihren Tagen:
Die Regel beginnt am Tag des Geräts (`rule_first_day`, der Datumsfehler).
- Exchange 2019 schickt die Definition einer eigenen Zone mit, in `GetItem`
und in `SyncFolderItems`. Gemessen ist das an einem Termin, den das
Programm selbst mit Definition angelegt hat (ganztägig, eigene Zone
UTC+03:00, Id „Customized Time Zone“, die Exchange so zurückgab): auf
Mittwoch verschoben, liegt er auf der Mitternacht dieser Zone, einen Tag
lang (232, 239). Ein Termin mit der Zone „Europe/Berlin“ ebenso auf
Berliner Mitternacht (236). Ein Termin vom iPhone oder aus einer
Einladung und die Ablehnung nach 237 sind nicht gemessen; Schritt 6 war
ohne Exchange im Apple-Kalender nicht machbar.
- Ein Termin mit Uhrzeit in der Zone W. Europe, wie Outlook ihn speichert
(vom Programm per EWS angelegt), in Aperio ganztägig gemacht, liegt einen
Tag auf Berliner Mitternacht.
- Exchange gibt Start- und Enddatum einer Serie in W. Europe ohne
`TimeZoneContext` mit Versatz zurück: `2026-11-04+01:00`.
- Ein Schnitt „dieser und alle folgenden“ an einer täglichen Serie mit
Uhrzeit zeigt den Schnitttag doppelt. Aperio kürzt die alte Serie mit
`UNTIL` eine Sekunde vor dem Schnitt, das Enddatum ist dessen Datum, und
Exchange zählt das Enddatum mit (235). Ein vor dem Schnitt gelöschtes
Vorkommen bleibt gelöscht. Nach dem Schreibcode von main wäre es dort
genauso.
- Ein in Aperio angelegter Einzeltermin, Montag 00:30, in einem Speichern
wöchentlich gemacht, steht danach sonntags um 23:30. Die Änderung schrieb
die Regel (ab Sonntag, dem Tag der gespeicherten Zone UTC, 234) und danach
die Zone, aber weder Beginn noch Ende. Die neue Zone hat die gespeicherte
Uhrzeit 23:30 behalten. In welcher Reihenfolge Exchange Regel und Zone
anwendet, zeigt das nicht: Die Regel nannte den Sonntag selbst, und eine
Zone, die die Uhrzeit behält, behält auch deren Tag; jede Reihenfolge
ergäbe sonntags 23:30. 234 bleibt abgeleitet (Runde 1), weder bestätigt
noch widerlegt. Nach dem Schreibcode von main wäre es dort genauso. Der
nächste PR schreibt die Zone, dann Beginn und Ende, dann die Regel am Tag
der neuen Zone, und misst, ob das richtig landet.
5. **Exchange und Microsoft 365 lesen Serien-Daten auf der Uhr der Serie** — `fix(ews, graph): read a series' dates on its own clock when writing`.
Danach messen, wie Microsoft 365 recurrenceTimeZone beim Zurücklesen behandelt.
Der Exchange-Teil ist mit PR 8a gebaut, zusammen mit 47a (57a), und im
Live-Test 8a gemessen. Offen ist
Microsoft 365; danach messen, wie es recurrenceTimeZone beim Zurücklesen
behandelt. Serien, die Aperio schon mit falschem Starttag geschrieben hat,
bleiben, wie sie sind (231): einmal verschieben und Wochentag oder Tag in
der Wiederholung neu wählen.
6. **Kalender melden, welche Zonen sie speichern** — `feat(plugin-core): calendars declare which series time zones they can store`.
`time_zones`: alle, keine (Handy-Kalender) oder nur bestimmte (Exchange). Das
Handy muss dafür auch die eingebauten Manifeste lesen; ob der Desktop sie
Expand Down Expand Up @@ -1046,9 +1112,22 @@ Handy im selben PR.
- welche Namen Kerio Connect und Zimbra kennen und was sie mit einem
unbekannten Namen tun.

Ungeprüft bleibt, ob Exchange eigene Zonendefinitionen und Namen, die nur in
der Windows-Registry stehen (Kamchatka, Mid-Atlantic), so zurückgibt, wie
Aperio sie liest: als keine Zone. Ungeprüft ist auch, ob Exchanges eigene
Ungeprüft bleibt, ob Exchange Namen, die nur in der Windows-Registry stehen
(Kamchatka, Mid-Atlantic), so zurückgibt, wie Aperio sie liest: als keine
Zone. Eine eigene Zonendefinition schickt Exchange 2019 in
`SyncFolderItems` und `GetItem` mit (Live-Test 8a, an einem per EWS
angelegten Termin); seit PR 8a liest ein ganztägiger Termin sie selbst, die
Uhr einer Serie behandelt sie weiter als keine Zone. Ungeprüft aus PR 8a sind
außerdem: ob Exchange bei einem Ändern die Regel vor der Zone anwendet, die
dieselbe Änderung danach schreibt (234; Schritt 9 des Live-Tests 8a kann das
nicht zeigen, weil jede Reihenfolge sonntags 23:30 ergibt); ein Termin mit
eigener Zone vom iPhone oder aus einer Einladung und
die Ablehnung nach 237 am echten Server; ob Exchange ein Ende in der Endzone
rundet, wenn Beginn und Ende verschiedene Zonen tragen (233, R3-2 legt es
nahe); was Exchange an einem Tag speichert, dessen Mitternacht die
gespeicherte Zone überspringt. Gemessen hat der Live-Test 8a, dass `EndDate`
inklusive ist (235) und dass eine neue Zone ohne Beginn und Ende die
gespeicherte Uhrzeit behält (siehe Stufe 4, „Gemessen“). Ungeprüft ist auch, ob Exchanges eigene
Zeitzonen-Regeln denen von Windows gleichen, an denen der Uhr-Wächter über die
Standardzonen gemessen ist.
- Ob der Desktop die eingebauten Manifeste für die Wiederholungs-Fähigkeiten
Expand Down
60 changes: 48 additions & 12 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -2673,8 +2673,9 @@ Siehe DESIGN §4.2.
- iOS-Gerätekalender: jedes Schreiben und Löschen nutzt `span:
.thisEvent` (`IosDeviceEventStore.swift`), trifft bei einer Serie also nur
das erste Vorkommen. Ungemessen.
- Exchange/Graph: ob `EndDate` inklusive ist — dann bliebe bei jedem
Kürzen ein Vorkommen zu viel. Ungemessen.
- Exchange: `EndDate` ist inklusive (Live-Test 8a, 2026-10-10). Ein
Kürzen mit Uhrzeit lässt den Schnitttag deshalb doppelt stehen; die
Korrektur ist ein eigener PR (235). Graph: ungemessen.
- Mitziehen „nur dieses Vorkommen“ an Kopien: erst der Platz in der
Serie, dann die Kopie (dieselbe Reihenfolge, die #92 in den Editoren
umgedreht hat).
Expand Down Expand Up @@ -2966,14 +2967,11 @@ Siehe DESIGN §4.2.
einer, die Aperio ohne Zone angelegt hat (Runde 2), und einer aus Outlook,
deren Startzone Aperios Änderung auf Greenwich gesetzt hatte (Runde 3).
Beide liegen bei Versatz 0; `Z` sagt dort nicht, ob es die UTC-Rechnung
der Anfrage oder die Zone der Serie meint. Dass das Enddatum ebenso eine
Zone trägt, ist gefolgert, nicht gemessen: gleicher Datentyp, und laut
Microsoft hängt EWS an zurückgegebene Werte eine Zone an. Ob Exchange bei
einer Serie in einer Zone abseits von UTC einen Versatz schreibt, ist
ungemessen. Aperio schickt keinen `TimeZoneContext`, und ohne ihn rechnet
EWS in UTC. Womöglich kommt `Z` also bei JEDER Serie, dann betraf der
Fehler jede Exchange-Serie mit Enddatum, auch die in Outlook angelegten.
Der Leser schnitt nur `T` und `+` ab. Bei `Z` und bei einem Versatz
der Anfrage oder die Zone der Serie meint. Der Live-Test 8a (2026-10-10)
hat für eine Serie in W. Europe ohne `TimeZoneContext` gemessen: Start- und
Enddatum kommen mit Versatz zurück, `2026-11-04+01:00`. `Z` kommt also
nicht bei jeder Serie; der Fehler traf Serien mit `Z` und mit einem Versatz
westlich von UTC. Der Leser schnitt nur `T` und `+` ab. Bei `Z` und bei einem Versatz
westlich von UTC wurde daraus eine Regel wie `UNTIL=20261105ZT235959Z`, die
beide Ausroller ablehnten: Die Serie erschien nur am Beginn ihres Masters,
dem ersten Termin der Regel, auch wenn dieses Vorkommen geändert oder
Expand All @@ -2993,9 +2991,47 @@ Siehe DESIGN §4.2.
zurück. Das gilt nur, falls Exchange `task:Recurrence` beim Auflisten
überhaupt liefert, und das ist ungeprüft (`tasks.rs`). Abhilfe wäre, jede
Aufgabenliste einmal neu zu lesen, etwa über eine Version im Aufgaben-Token.
🚩 **Update-Regel für ganztägige Exchange-Termine** (47a) und
↻ **Update-Regel für ganztägige Exchange-Termine** (47a) und
**Datumsfehler** (Startdatum, Wochentag, Monatstag und Monat aus dem
UTC-Datum): eigene PRs nach Runde 3.
UTC-Datum): gebaut in PR 8a (2026-10-10, Entscheidungen 231-239). Eine
Serie beginnt an ihrem ersten Tag auf der Uhr, auf der Exchange sie
wiederholt; ein ganztägiger Tag geht beim Ändern auf Mitternacht in der
gespeicherten Zone jeder Grenze; eigene Zonen-Definitionen werden gelesen;
eine unlesbare Zone lehnt den Tag mit eigenem Satz ab (237). Live-Test 8a
am 10.10.2026: Schritte 1 bis 5 und 7 bestanden. Schritt 6 (ein Termin vom
iPhone) war nicht machbar; ein Testprogramm hat stattdessen eigene Termine
per EWS angelegt, eine eigene Zone und „Europe/Berlin“, beide bestanden.
Ungemessen bleiben ein Termin mit eigener Zone vom iPhone oder aus einer
Einladung und die Ablehnung nach 237 am echten Server (Einzelheiten in
DESIGN, Stufe 4, „Gemessen“).
🚩 **Schnitttag doppelt** (235, gemessen im Live-Test 8a): Ein Schnitt „dieser
und alle folgenden“ an einer Exchange-Serie mit Uhrzeit zeigt den Schnitttag
in beiden Serien. Die alte Serie endet mit `UNTIL` eine Sekunde vor dem
Schnitt, das Enddatum ist dessen Datum, und Exchange zählt es mit. Das
Enddatum muss der Tag des letzten Vorkommens vor dem Schnitt sein. Eigener
PR, nach der Zonen-Reihenfolge und vor 8b. Ein vor dem Schnitt gelöschtes
Vorkommen bleibt gelöscht.
🚩 **Serien mit falschem Starttag** (231): Was Aperio vor 8a geschrieben hat,
bleibt so. Einmal verschieben und Wochentag oder Tag in der Wiederholung
neu wählen; eine wöchentliche Serie ohne gewählten Wochentag trägt in der
Regel den Wochentag davor (für Montag: Sonntag), eine zweiwöchentliche kann
eine Woche verrutscht sein.
🚩 **Microsoft 365: derselbe Datumsfehler** (235): eigener PR.
🚩 **Zone und Wiederholung in einem Ändern:** Wird ein Termin mit Uhrzeit
zur Serie mit neuer Zone, behält Exchange die gespeicherte Uhrzeit und gibt
ihr die neue Zone, der Termin wandert um den Versatz (Runde 1, Stufen 9
und 12: eine Zone nach Beginn und Ende). Der Live-Test 8a hat es für eine
Änderung ohne Beginn und Ende gemessen: Ein in Aperio angelegter
Einzeltermin am Montag um 00:30, wöchentlich gemacht, steht danach sonntags
um 23:30. Die Änderung schrieb nur die Regel (ab dem Tag der alten Zone UTC:
Sonntag, 234) und danach die Zone; die Zone hat die gespeicherte Uhrzeit
behalten. Über die Reihenfolge von Regel und Zone sagt das nichts: Jede
Reihenfolge ergibt sonntags 23:30, weil die Zone mit der Uhrzeit auch den
Tag behält. 234 bleibt abgeleitet. Nächster PR nach 8a: die Zone schreiben,
dann Beginn und Ende, auch wenn sie sich nicht ändern, dann die Regel am Tag
der neuen Zone, und messen, ob das richtig landet. Dass die Zone zuerst die
Zeitpunkte stehen lässt, ist nur an einer ganztägigen Serie gemessen
(Runde 2, B4).
🚩 **Open-Source-Hinweise** in der Desktop- und der Handy-App (40a): CLDR und
die eingebauten ICU4X-Bibliotheken nennen.
🚩 **Wenn der EWS-Adapter das Repository verlässt,** müssen `cldr/`, die
Expand Down
Loading
Loading