feat(core): time zone for date formatting (#DS-3248) - #1936
Conversation
|
Visit the preview URL for this PR (updated for commit cf09293): https://koobiq-next--prs-1936-zx80w39l.web.app (expires Sat, 29 Aug 2026 09:34:28 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 Sign: c9e37e518febda70d0317d07e8ceb35ac43c534c |
There was a problem hiding this comment.
Pull request overview
Introduces first-class, application-configurable time zone support to core date formatting/parsing so that pipes, DateFormatter, adapters, calendar, and date/time inputs can render consistently across browser/SSR and react to runtime time zone changes.
Changes:
- Added
KBQ_DATE_TIMEZONE,KbqDateTimezoneService,kbqDateTimezoneProvider,kbqResolveTimezoneOffset, andKbqTimezoneLiketo core public API. - Updated core date formatter pipes and datepicker/timepicker surfaces to re-render/re-initialize when the active time zone changes.
- Extended Luxon and Moment Angular adapters to apply the configured time zone during parsing/formatting/date construction; added docs, dev SSR wiring, and unit tests.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tools/public_api_guard/components/core.api.md | Public API snapshot updated to include new timezone-related exports. |
| tools/cspell-locales/ru.json | Added Russian words to local spelling dictionary. |
| packages/components/timezone/timezone.utils.ts | Reused core timezone offset resolution for offset parsing in timezone utilities. |
| packages/components/timepicker/timepicker.directive.ts | Re-render timepicker display when timezone changes. |
| packages/components/datepicker/month-view.component.ts | Re-initialize month view on timezone changes so “today”/cells match the active zone. |
| packages/components/datepicker/datepicker-input.directive.ts | Reformat date input when timezone changes to avoid parsing against a different zone on the next edit. |
| packages/components/core/formatters/date/formatter.spec.ts | Added tests covering timezone-aware rendering and runtime timezone changes (pure vs impure pipes). |
| packages/components/core/formatters/date/formatter.pipe.ts | Made impure formatter pipes react to active timezone changes via KbqDateTimezoneService. |
| packages/components/core/formatters/date/date-formatter.ru.md | Documented timezone configuration, runtime switching, scoping, and SSR considerations (RU). |
| packages/components/core/formatters/date/date-formatter.en.md | Documented timezone configuration, runtime switching, scoping, and SSR considerations (EN). |
| packages/components/core/datetime/timezone.ts | Added timezone token/service/provider and offset resolution utilities (new core feature). |
| packages/components/core/datetime/index.ts | Exported the new timezone module from datetime barrel. |
| packages/components-dev/ssr/timezone.ts | Added dev SSR providers to keep server/client timezone consistent via TransferState and a cookie. |
| packages/components-dev/ssr/config.ts | Wired dev browser-side timezone providers into SSR dev app config. |
| packages/components-dev/ssr/config.server.ts | Wired dev server-side timezone provider into SSR dev server config. |
| packages/components-dev/date-pipes/template.html | Added UI control to toggle timezone in dev date-pipes app. |
| packages/components-dev/date-pipes/module.ts | Added timezone toggling logic and injected KbqDateTimezoneService in dev app. |
| packages/angular-moment-adapter/package.json | Added @koobiq/date-adapter peer dependency for new adapter typings/overrides. |
| packages/angular-moment-adapter/adapter/moment-date-adapter.ts | Applied configured timezone semantics across moment adapter operations. |
| packages/angular-moment-adapter/adapter/moment-date-adapter.spec.ts | Added tests for moment adapter timezone behavior and edge cases. |
| packages/angular-luxon-adapter/package.json | Added @koobiq/date-adapter peer dependency for new adapter typings/overrides. |
| packages/angular-luxon-adapter/adapter/date-adapter.ts | Applied configured timezone semantics across luxon adapter operations. |
| packages/angular-luxon-adapter/adapter/date-adapter.spec.ts | Added tests for luxon adapter timezone behavior and edge cases. |
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| export const kbqResolveTimezoneOffset = (timezone: KbqTimezoneLike, timestamp: number): number | null => { | ||
| if (timezone === 'system') return null; | ||
|
|
||
| if (typeof timezone === 'number') return Number.isFinite(timezone) ? timezone : null; | ||
|
|
||
| const fixedOffset = parseFixedOffset(timezone); |
| "отрендерен", | ||
| "отрисованного", | ||
| "отрисованные", | ||
| "отрисовку", |
There was a problem hiding this comment.
название ветки неверное: fix -> feature
There was a problem hiding this comment.
после влития это будет не важно, главное что не наоборот :)
| this._localeChanges.next(locale); | ||
| }; | ||
|
|
||
| override today(): DateTime { |
There was a problem hiding this comment.
Предлагаю логику с timezone вынести в @koobiq/date-adapter и связанные пакета @koobiq/luxon-date-adapter и т.д. для совместимости с React
Не в этой задаче
There was a problem hiding this comment.
там ангуляровский сервис и на него все завязано.. ладн потом подумаем
Follow-up on the review of the time zone token. Crashes and wrong values: - guard `kbqResolveTimezoneOffset` against a non-finite timestamp: an invalid date reached `Intl.DateTimeFormat.formatToParts` and threw a RangeError out of every date pipe - treat a date-only ISO string as a calendar day, not an instant, in both adapters - hand moment the offset as `±HH:mm`: it reads a number below 16 as hours, not minutes - override `startOf` and the `addCalendar*` family in the moment adapter, and re-resolve the offset once a shift has crossed a transition - build wall-clock dates in the active zone rather than moving them into it, so a DST gap in the host zone cannot shift them first - zone the input before truncating it in the luxon `startOf` - fall back to the host zone for a non-finite numeric offset Behaviour kept as it was: - `useUtc` keeps converting instants while no zone is configured, instead of switching to the wall-clock semantics the token introduces API and wiring: - `kbqDateTimezoneProvider` provides `KbqDateTimezoneService` too, so scoping a zone to a subtree is no longer a silent no-op - `KbqDateTimezoneService.changes` re-renders the date inputs and the calendar - the offset parser accepts seconds and the unsigned form the timezone picker emits, rejects an out-of-range one, and `parseOffset` delegates to it - bound the `Intl.DateTimeFormat` cache - declare `@koobiq/date-adapter` as a peer dependency of both adapters
…y (#DS-3248) - api-extractor emits `constructor()` before the alphabetically ordered members, while the hand-written snapshot had `changes` above it - `angular-moment-adapter` has imported `moment` directly since the time zone work landed, so `npm install` consumers need it declared; `@koobiq/moment-date-adapter` pins the same range
`kbqResolveTimezoneOffset` bounded a string offset to ±14:00 but accepted any finite number, so the two forms of the same value disagreed and an offset from unvalidated input could be far outside anything a zone has ever used, or a fraction of a minute that neither date library renders sensibly. The numeric branch is now bounded and rounded like the string one, and the luxon adapter routes numbers through it instead of building a `FixedOffsetZone` straight from the input, so both adapters fall back to the host zone on the same values.
dfde6b5 to
96275f1
Compare
No description provided.