[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

[typescript-fetch] centralise date handling, add dateLibrary - #24722

Merged
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library
Aug 17, 2026
Merged

[typescript-fetch] centralise date handling, add dateLibrary#24722
wing328 merged 7 commits into
masterfrom
LeComptoirDesPharmacies-feat/typescript-fetch-date-library

Conversation

@wing328

@wing328wing328 commented Aug 17, 2026

Copy link
Copy Markdown
Member

based on #24637 with updated samples.

all TS tests passed.

PR checklist

  • Read the contribution guidelines.
  • Run the following to build the project and update samples:
    ./mvnw clean package || exit
    ./bin/generate-samples.sh ./bin/configs/*.yaml || exit
    ./bin/utils/export_docs_generators.sh || exit
    
    (For Windows users, please run the script in WSL)
    Commit all changed files.
    This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
    These must match the expectations made by your contribution.
    You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example ./bin/generate-samples.sh bin/configs/java*.
    IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
  • If your PR is targeting a particular programming language, @mention the technical committee members, so they are more likely to review the pull request.

Summary by cubic

Centralizes date handling for typescript-fetch and adds a dateLibrary option to choose Date (default) or string. Fixes format: date bugs (incorrect form param serialization and UTC day shifts) by using the local calendar for date and UTC for date-time.

  • Runtime: all date parsing/serialization now uses parseDate, parseDateTime, serializeDate, and serializeDateTime in runtime.ts; querystring and path/query/form params route through these.
  • Generator: new additionalProperties.dateLibrary option (date | string); withoutRuntimeChecks implies string. Docs updated.
  • Templates: models and oneOf guards align with helpers; date imports only when needed via x-hasDateVars. ES6-safe code; preserves years 0000–0099 and rejects invalid dates.
  • Tests/samples: added a fixture covering all date locations and two sample builds (date and string).

Migration

  • If your client expects string dates, set -p dateLibrary=string (or dateLibrary: string in config). Regenerate and update types accordingly.
  • If you relied on withoutRuntimeChecks for string dates, no change; to get Date, disable that flag and/or set -p dateLibrary=date.

Written for commit b71f03e. Summary will update on new commits.

Review in cubic

b2land others added 7 commits August 12, 2026 09:48
…mat: date
Date handling was spread across four templates, each inlining its own
expression. That had three consequences:
1. `format: date` was not handled at all for form parameters, so a Date
was appended raw and stringified by the browser
("Wed Aug 05 2026 00:00:00 GMT+0200 (…)") instead of "2026-08-05".
2. `format: date` shifted by a day everywhere except UTC, in one direction
or the other. Parsing (`new Date('2026-08-05')`) and serialising
(`.toISOString().substring(0, 10)`) both work in UTC, but consumers do
not: a date picker builds local midnight and display reads local
getters. West of UTC a date from the API displays as the previous day;
east of UTC a locally built date is sent as the previous day. An RFC
3339 full-date has no offset, so both ends have to use the same wall
clock — they now both use the local calendar. `format: date-time` is a
genuine instant and stays UTC.
3. Whether dates were represented as Date or string was decided by
`withoutRuntimeChecks`, an unrelated flag about payload validation.
All call sites (models, oneOf models, path/query/form parameters and the
querystring helper) now route through serializeDate/serializeDateTime and
parseDate/parseDateTime in runtime.ts, so the representation is defined in
one place. The new `dateLibrary` option (`date`, the default and previous
behaviour, or `string`) makes the choice explicit; `withoutRuntimeChecks`
implies `string`, as before, since there is no model code left to convert
with.
Adds a spec fixture covering every location a date can appear in, two
sample builds (one per option value), and tests for the option, the
fallback and the serialisation semantics.
…es, unused imports
- serializeDate no longer uses padStart, which is ES2017: the es6-target
sample did not compile against its own tsconfig.
- parseDate builds the local date with setFullYear, so years 0000-0099 keep
their century instead of picking up the multi-argument Date constructor's
1900 offset ("0045-08-05" was parsed as 1945).
- parseDate rejects components that roll over, so an out-of-range date or a
day the local zone skipped returns Invalid Date rather than a plausible
wrong one. Previously "2026-13-45" became 2027-02-14.
- serializeDate throws RangeError on an invalid Date instead of emitting
"0NaN-NaN-NaN", matching serializeDateTime.
- Models without a date property no longer import the date helpers, via a
new x-hasDateVars extension mirroring the template's own branches. This
reverts most of the sample churn from the previous commit.
Drops testDateFormatUsesTheLocalCalendar: runtime.ts is identical for every
spec, so asserting its body only restated the template. The per-build
tsconfig typecheck covers the ES6 regression properly.
The oneOf branches tested a value with `new Date(json)` but converted it with
parseDate, so the two could disagree: "2026-02-30" passes the lenient test (V8
rolls it to March 2) and then parseDate rejects it, leaving the branch selected
and returning Invalid Date. Testing with the same helper that does the
conversion lets the oneOf fall through to another branch instead.
Adds a oneOf date member to the date-handling fixture. No sample in the repo
exercised these branches, so the generated form of the guard was invisible in
the samples; only the scalar variant is left out, because a scalar oneOf
primitive already fails `tsc --strict` on master (it can return undefined,
which is not in the union).
Drops the comment justifying the ES6-safe padding: the per-build tsconfig
typecheck already fails if someone reaches for padStart again.
… the date helpers
Upstream #24509 null-guarded required date properties; keep that guard
but route the conversion through parseDate/serializeDate. Port the form
param date handling into the apisFormParams partial extracted by #23935,
and regenerate the affected samples.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…runtime.mustache
Co-authored-by: Esteban Gehring <esteban.gehring@gmail.com>
@wing328wing328 added Client: TypeScript Enhancement: Code Cleanup General refactoring, removal of deprecated things, commenting, etc. labels Aug 17, 2026
@wing328wing328 added this to the 7.25.0 milestone Aug 17, 2026
@wing328wing328 changed the title Le comptoir des pharmacies feat/typescript fetch date library[typescript-fetch] centralise date handling, add dateLibraryAug 17, 2026
@wing328
wing328 marked this pull request as ready for review August 17, 2026 09:27
@wing328
wing328 merged commit 51433f0 into masterAug 17, 2026
245 of 477 checks passed
@wing328
wing328 deleted the LeComptoirDesPharmacies-feat/typescript-fetch-date-library branch August 17, 2026 09:27
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Client: TypeScriptEnhancement: Code CleanupGeneral refactoring, removal of deprecated things, commenting, etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@wing328@b2l