Angular 5, HttpClient changes Date fields to UTC

Viewed 14560

I Have an object which has a Date type property on client side. When I try to send object via HttpClient.post to server, property's value changes to UTC timezone.

On client side value is Sun Nov 26 2017 00:00:00 GMT+0300 (Turkey Standard Time) but when it goes to server, changes to : 25.11.2017 21:00:00

How can I control This?

This is my class.

export interface IBill {
   BillID : number;
   SubscriptionID:number;
   SiteID : number;
   SubscriptionName: string;
   Amount: number;
   Date: Date;
   PaymentDeadline: Date;
   Virtual: boolean;
   Portioned: boolean;
   Issuanced: boolean;
   FinancialTransactionComment : string;}

I create an object of this while filling a ng-form, then call following Http.post :

let bill = this.formData;
this.http.post(this.configuration.ServerWithApiUrl + url, bill , { headers: headers, withCredentials: true, observe: "response", responseType: 'text' })
        .map((response) => {
            return this.parseResponse(response);
        }).catch(
        (err) =>
            this.handleError(err));
3 Answers

Use an HttpInterceptor for modifying request body on put/post requests. Recursively update all date fields by creating corrected Date objects.

Sample code:

@Injectable() export class UpdateDateHttpInterceptor implements HttpInterceptor {

  intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    this.startLoading();
    if (req.method === 'POST' || req.method === 'PUT') {
        this.shiftDates(req.body);
    }
  }

  shiftDates(body) {
    if (body === null || body === undefined) {
        return body;
    }

    if (typeof body !== 'object') {
        return body;
    }

    for (const key of Object.keys(body)) {
        const value = body[key];
        if (value instanceof Date) {
            body[key] = new Date(Date.UTC(value.getFullYear(), value.getMonth(), value.getDate(), value.getHours(), value.getMinutes()
                , value.getSeconds()));
        } else if (typeof value === 'object') {
            this.shiftDates(value);
        }
    }
  }

A little late but, Angular internally uses JSON.stringify to serialize HttpRequest body (typeof object). JSON.stringify converts JavaScript Date to ISO string. To overcome this either override Date.prototype.toJSON using some third party libraries like moment.js format function.

Date.prototype.toJSON = function() {
    return  moment(this).format();
}

The problem with this approach is it will alter the global Date object. Alternatively you can create a function that creates a proxy object that is sent to server.

export function prepareRequestBody(body: any): any {
    if (typeof body === 'object') {
        return new Proxy(body, {
            get(target, prop, receiver) {
                if (target[prop] instanceof Date) {
                    return moment(target[prop]).format();
                }
                return target[prop]
            }
        })
    }

    return body
}

  
Related