Date Transformer
An Angular HTTP Interceptor ↗️ that automatically converts date strings from API responses into JavaScript Date objects.
Usage
The Date Transformer is generated by default when you set the dateType option to 'Date' in your OpenAPI configuration.
The interceptor will be applied automatically to your HTTP client, if you are using the provideNgOpenapi provider and the enableDateTransform option isn't disabled.
Manual Setup
If you chose to configure the OpenAPI client manually or want to add the Date Transformer interceptor separately, you can do so by applying the DateInterceptor to your HTTP client in your app.config.ts.
import { ApplicationConfig } from "@angular/core";
import { provideHttpClient, withInterceptors } from "@angular/common/http";
import { DateInterceptor } from "./client/utils/date-transformer";
export const appConfig: ApplicationConfig = {
providers: [
provideHttpClient(withInterceptors([DateInterceptor])),
{ provide: BASE_PATH, useValue: "https://api.example.com" },
],
};Example Date Transformer
// client/utils/date-transformer.ts
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, HttpResponse } from "@angular/common/http";
import { Injectable } from "@angular/core";
import { Observable } from "rxjs";
import { map } from "rxjs/operators";
export const ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:?\d{2})?$/;
export function transformDates(obj: any, dateRegex: RegExp = ISO_DATE_REGEX): any {
if (obj === null || obj === undefined || typeof obj !== "object") {
return obj;
}
if (obj instanceof Date) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => transformDates(item, dateRegex));
}
if (typeof obj === "object") {
const transformed: any = {};
for (const key of Object.keys(obj)) {
const value = obj[key];
if (typeof value === "string" && dateRegex.test(value)) {
transformed[key] = new Date(value);
} else {
transformed[key] = transformDates(value, dateRegex);
}
}
return transformed;
}
return obj;
}
@Injectable()
export class DateInterceptor implements HttpInterceptor {
/** @param dateRegex Optional override for the pattern used to detect ISO date strings. */
constructor(private readonly dateRegex: RegExp = ISO_DATE_REGEX) {}
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
return next.handle(req).pipe(
map((event) => {
if (event instanceof HttpResponse && event.body) {
return event.clone({ body: transformDates(event.body, this.dateRegex) });
}
return event;
}),
);
}
}Recognized Formats
ISO_DATE_REGEX matches a full RFC 3339 / ISO 8601 date-time with optional fractional seconds (of any length) and an optional Z or numeric timezone offset (±hh:mm or ±hhmm):
2024-01-15T10:30:00Z2024-01-15T10:30:00.123Z2024-01-15T10:30:00.04— any number of fractional-second digits2024-01-15T10:30:00.7559265+02:00— numeric timezone offset2024-01-15T10:30:00+0200— offset without colon2024-01-15T10:30:00
The pattern is intentionally strict (full date-time only) so plain strings such as a bare year ("2024") or a numeric ID are never accidentally turned into Date objects.
Customizing the Regex
If your API uses a format the default pattern doesn't cover, override it via the provider instead of editing the generated file:
provideNgOpenapi({
basePath: "https://api.example.com",
dateTransformRegex: /your-custom-pattern/,
});Both transformDates and DateInterceptor accept the regex directly as well, for manual interceptor setups:
new DateInterceptor(/your-custom-pattern/);
transformDates(responseBody, /your-custom-pattern/);