Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4: Date pipe, UTC Time to local time: How to tell Angular the current time zone?

We are using Angular 4 together with a MVC Application written in .net core. The data is received using a SignalR Service, the hub is written in C#. The database provides a Datetime2(7) Field (T-SQL), the content, that gets received, looks like this (for the date-field):

dueDt:"2017-10-02T08:54:00"

This time is a UTC Time. We are living in a +2 time zone. Now, in the CSHTML-File, we display this value like this:

 <small>Due: {{item.dueDt | date:'dd.MM.yy HH:mm'}}</small>

which display something like: 27.09.17 12:43 which is fine, the problem is just that our timezone is not +0 but +2, so it should display 14:43 as the time.

I have read somewhere that Angulars DatePipe uses the clients local timezone, but that doesnt seem to happen here. (I have tried this with chrome, firefox and Edge - there is no difference). Does anybody have an idea, why this happens or how I can tell Angular what the local timezone is? I have tried including angular-moment but it doesnt really work either. (I can detail that, if that seems important, but it is a different issue).

like image 284
MPoutanen Avatar asked Sep 29 '17 14:09

MPoutanen


2 Answers

Setting Json Deserializer options to UTC does the trick.

The default DateTime Kind for Json deserializer is RoundTripKind. When the server side datetime object's Kind is set to Unspecified, RoundTripKind doesn't add the Z at the end of the deserialized string. I guess this is the right behaviour but if we assume all date objects are actually in UTC time than we can say to Json Deserializer to consider it.

And now date pipe actually gets that the time is in UTC and shows it in local time, by default apparently

services.AddMvc().AddJsonOptions(options =>
            {
                options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
            });

And strings like "2019-03-15T21:00:00" will become "2019-03-15T21:00:00Z"

See: Newtonsoft Json.Net DateTimeZoneHandling setting

like image 172
mkb Avatar answered Sep 30 '22 06:09

mkb


I have done something similar using moment.js, but the Locale it's actually specific to each user configuration for Locale and date pattern:

import { Injectable, Pipe, PipeTransform } from '@angular/core';
import * as moment from 'moment';
import { Observable } from 'rxjs/Rx';
import { UserService } from '../security/user/user.service';

@Pipe({
    name: 'formatDate'
})
@Injectable()
export class DateTimePipe implements PipeTransform {

    constructor(private userService: UserService) {

    }

    /**
     * Asynchronous pipe, transforms a date into a formatted date.
     * The transformation is based on the 'locale' and 'pattern' properties from the current user preferences.
     * Usage: this pipe need to be followed by the'async' pipe, since it returns an Observable.
     */
    transform(value: any, showTime?: boolean): Observable<string> {
        if (value) {
            return this.userService.getPreferences()
                .map(prefs => {
                    const locale = prefs.preferences.get('locale');

                    let pattern;
                    if (showTime) {
                        pattern = prefs.preferences.get('dateTimeFormat') || 'DD/MM/YYYY HH:mm';
                    } else {
                        pattern = prefs.preferences.get('dateFormat') || 'DD/MM/YYYY';
                    }

                    moment.locale(locale);

                    let date = value instanceof Date ? value : new Date(value);
                    return moment(date).format(pattern);
                });
        }
        return Observable.of(value);
    }
}

you can change local with moment as well

moment.locale('en_GB')

See full options here https://momentjs.com/

like image 34
nuvio Avatar answered Sep 30 '22 05:09

nuvio