Skip to content

feat(core): time zone for date formatting (#DS-3248) - #1936

Merged
lskramarov merged 4 commits into
mainfrom
fix/DS-3248
Aug 26, 2026
Merged

feat(core): time zone for date formatting (#DS-3248)#1936
lskramarov merged 4 commits into
mainfrom
fix/DS-3248

Conversation

@lskramarov

Copy link
Copy Markdown
Contributor

No description provided.

@lskramarov lskramarov self-assigned this Aug 26, 2026
Copilot AI lite review requested due to automatic review settings August 26, 2026 09:15
@lskramarov lskramarov added the enhancement New feature or request label Aug 26, 2026
@github-actions

github-actions Bot commented Aug 26, 2026

Copy link
Copy Markdown

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

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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, and KbqTimezoneLike to 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.

Comment on lines +101 to +106
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);
"отрендерен",
"отрисованного",
"отрисованные",
"отрисовку",

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

название ветки неверное: fix -> feature

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

после влития это будет не важно, главное что не наоборот :)

this._localeChanges.next(locale);
};

override today(): DateTime {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Предлагаю логику с timezone вынести в @koobiq/date-adapter и связанные пакета @koobiq/luxon-date-adapter и т.д. для совместимости с React

Не в этой задаче

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

там ангуляровский сервис и на него все завязано.. ладн потом подумаем

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.
@lskramarov
lskramarov merged commit 822cbd4 into main Aug 26, 2026
0 of 2 checks passed
@lskramarov
lskramarov deleted the fix/DS-3248 branch August 26, 2026 16:27
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants