Jak ustawić ustawienia regionalne w DatePipe w Angular 2?

138

Chcę wyświetlić datę w formacie europejskim, dd/MM/yyyyale używając formatu DatePipe shortDate , wyświetla się tylko w amerykańskim stylu daty MM/dd/yyyy.
Zakładam, że domyślne ustawienie regionalne to en_US. Może brakuje mi dokumentów, ale jak mogę zmienić domyślne ustawienia regionalne w aplikacji Angular2? A może jest jakiś sposób na przekazanie niestandardowego formatu do DatePipe?

nsbm
źródło
1
Też chciałbym to wiedzieć. Zauważyłem, że dokumenty potoku daty, które wyjaśniają kolejność y i d w ciągu formatu, są ignorowane, ponieważ kolejność jest ustalana przez ustawienia regionalne. Ale nie ma wskazówek, jak ustawić (lub nawet uzyskać) ustawienia regionalne.
Mark Farmiloe

Odpowiedzi:

275

Począwszy od Angular2 RC6, możesz ustawić domyślne ustawienia regionalne w module aplikacji, dodając dostawcę:

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "en-US" }, //replace "en-US" with your locale
    //otherProviders...
  ]
})

Rury Waluta / Data / Liczba powinny uwzględniać ustawienia regionalne. LOCALE_ID jest nieprzezroczystym tokenem , który ma zostać zaimportowany z angular / core.

import { LOCALE_ID } from '@angular/core';

W przypadku bardziej zaawansowanego przypadku możesz chcieć pobrać lokalizację z usługi. Ustawienia regionalne zostaną rozwiązane (raz) po utworzeniu komponentu używającego potoku daty:

{
  provide: LOCALE_ID,
  deps: [SettingsService],      //some service handling global settings
  useFactory: (settingsService) => settingsService.getLanguage()  //returns locale string
}

Mam nadzieję, że to działa dla Ciebie.

korona
źródło
43
Jestem zdumiony, że to nadal nie wydaje się być nigdzie udokumentowane. Nie na stronie Date Pipe ( angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html ), nie na stronie ogólnej rur ( angular.io/docs/ts/latest/guide/pipes .html ) i to pytanie jest właściwie pierwszym trafieniem w Google ( google.com/search?q=angular%202%20locales&rct=j ). Świetne znalezisko.
JP ten Berge
2
Aby użyć potoku w kodzie, musisz teraz sformatować go jako new CurrencyPipe('en-US');. Mam nadzieję, że jest to przydatne do czegoś, ponieważ pojawiło się to jako pierwszy wynik podczas wyszukiwania w Google mojego problemu.
Ash Blue
1
@corolla Czy możesz rzucić trochę światła na tę usługę? Chciałbym zmienić ustawienia regionalne, gdy aplikacja jest uruchomiona, czy jest to możliwe w przypadku tej usługi? A jak wdrożyłbym taką usługę?
Martijn van den Bergh
1
@MartijnvandenBergh, usługa po prostu zwraca ciąg znaków regionalnych - nic nadzwyczajnego. Mieliśmy mieszane wyniki podczas próby zmiany ustawień regionalnych podczas działania aplikacji. Skończyło się na ponownym ładowaniu strony, aby obsłużyć wszystkie sprawy. YMMV.
corolla
1
Również bardzo się zmagałem z tym tematem i mam nadzieję, że artykuł, o którym napisałem, może niektórym pomóc: medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
Michael Karén
72

Rozwiązanie z LOCALE_ID jest świetne, jeśli chcesz raz ustawić język dla swojej aplikacji. Ale to nie działa, jeśli chcesz zmienić język w czasie wykonywania. W tym przypadku możesz zaimplementować niestandardowy potok daty.

import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Pipe({
  name: 'localizedDate',
  pure: false
})
export class LocalizedDatePipe implements PipeTransform {

  constructor(private translateService: TranslateService) {
  }

  transform(value: any, pattern: string = 'mediumDate'): any {
    const datePipe: DatePipe = new DatePipe(this.translateService.currentLang);
    return datePipe.transform(value, pattern);
  }

}

Teraz, jeśli zmienisz język wyświetlania aplikacji za pomocą TranslateService (zobacz ngx-translate )

this.translateService.use('en');

formaty w Twojej aplikacji powinny być aktualizowane automatycznie.

Przykład użycia:

<p>{{ 'note.created-at' | translate:{date: note.createdAt | localizedDate} }}</p>
<p>{{ 'note.updated-at' | translate:{date: note.updatedAt | localizedDate:'fullDate'} }}</p>

lub sprawdź mój prosty projekt „Notatki” tutaj .

wprowadź opis obrazu tutaj

Milan Hlinák
źródło
Otrzymuję błąd analizy szablonu; nie można skompilować filtra „localizedDate”, którego użyłem w taki sam sposób, jak sugerowano.
Prasad Shinde
Czy poprawnie zadeklarowałeś LocalizedDatePipe? Zobacz pipe.module.ts w moim przykładowym projekcie .
Milan Hlinák,
Tak, rozwiązałem to wcześniej, @Milan Hlinak Powinienem był odpowiedzieć tylko wtedy na mój komentarz. Ale w każdym razie dziękuję za szybką odpowiedź. Świetnie Ci idzie.
Prasad Shinde
Najwyraźniej tego właśnie szukałem. Szkoda tylko, że do zmiany
ustawień
2
Działa, ale zwróć uwagę, że użycie „nieczystych” rur jest wolniejsze niż „czystych”. Jak mówi przewodnik Angular : Angular wykonuje zanieczyszczoną rurę podczas każdego cyklu wykrywania zmiany komponentu. Zanieczyszczona potokka jest wywoływana często, tak często, jak każde naciśnięcie klawisza lub ruch myszy. Mając to na uwadze, zastosuj nieczystą rurę z wielką ostrożnością. Kosztowna, długa rura może zniszczyć komfort użytkowania.
Luca Ritossa
64

Z angular5powyższą odpowiedzią już nie działa!

Poniższy kod:

app.module.ts

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "de-at" }, //replace "de-at" with your locale
    //otherProviders...
  ]
})

Prowadzi do następującego błędu:

Błąd: brak danych regionalnych dla ustawień regionalnych „de-at”.

Ze angular5trzeba załadować i zarejestrować używany plik lokalizacji na własną rękę.

app.module.ts

import { NgModule, LOCALE_ID } from '@angular/core';
import { registerLocaleData } from '@angular/common';
import localeDeAt from '@angular/common/locales/de-at';

registerLocaleData(localeDeAt);

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "de-at" }, //replace "de-at" with your locale
    //otherProviders...
  ]
})

Dokumentacja

zgue
źródło
Rzeczywiście, jeśli potrzebujesz użyć innej lokalizacji niż en-US, powinieneś ją zarejestrować. Dzięki za odpowiedź, @zgue
MikkaRin
1
OK, to uchroniło mnie przed kolejnym bólem głowy .. Dzięki! Dokument jest trochę skomplikowany, ponieważ myślałem, że registerLocaleDatato wystarczy, cóż, nie jest.
niebezpieczeństwo 89
1
Najlepsza odpowiedź dla Ionic 4!
parrycima
22

Jeśli używasz TranslateServicefrom @ngx-translate/core, poniżej znajduje się wersja bez tworzenia nowego potoku, która działa z dynamicznym przełączaniem w czasie wykonywania (testowana na Angular 7). Korzystanie z localeparametru DatePipe ( dokumentacja ):

Najpierw zadeklaruj ustawienia regionalne, których używasz w swojej aplikacji, np. W app.component.ts:

import localeIt from '@angular/common/locales/it';
import localeEnGb from '@angular/common/locales/en-GB';
.
.
.
ngOnInit() {
    registerLocaleData(localeIt, 'it-IT');
    registerLocaleData(localeEnGb, 'en-GB');
}

Następnie używaj potoku dynamicznie:

myComponent.component.html

<span>{{ dueDate | date: 'shortDate' : '' : translateService.currentLang }}</span>

myComponent.component.ts

 constructor(public translateService: TranslateService) { ... }
knnhcn
źródło
2
To zaskakująco miłe. Nie potrzebujesz do tego nawet @ ngx-translate. Czy możesz wyjaśnić, co robi stwierdzenie w szablonie?
lama
2
@lama, dueDate (dowolna data, którą chcesz sformatować) | date: 'shortDate' (1. parametr potoku daty odpowiadający 'formatowi') : '' (2. parametr => strefa czasowa, "Gdy nie jest podany , używa strefy czasowej systemu lokalnego użytkownika końcowego".) : trasnlateService.currentLang (3. parametr => lokalnie), chick this DatePipe
Diego Osornio
co jeśli masz dostosowany format? czy to też byłoby zlokalizowane?
Wildhammer
12

Zajrzałem do date_pipe.ts i są tam dwie interesujące informacje. u góry znajdują się następujące dwie linie:

// TODO: move to a global configurable location along with other i18n components.
var defaultLocale: string = 'en-US';

U dołu jest ta linia:

return DateFormatter.format(value, defaultLocale, pattern);

To sugeruje mi, że potok daty jest obecnie zakodowany na stałe jako „en-US”.

Proszę mnie oświecić, jeśli się mylę.

Mark Farmiloe
źródło
Możesz sprawdzić odpowiedź Corolli poniżej. Jest bardziej aktualny i stanowi świetne rozwiązanie.
Mark Langer,
9

W app.module.ts dodaj następujące importy. Jest to lista opcji Locale tutaj .

import es from '@angular/common/locales/es';
import { registerLocaleData } from '@angular/common';
registerLocaleData(es);

Następnie dodaj dostawcę

@NgModule({
  providers: [
    { provide: LOCALE_ID, useValue: "es-ES" }, //your locale
  ]
})

Użyj rur w html. Oto dokumentacja kątowa .

{{ dateObject | date: 'medium' }}
Alejandro del Río
źródło
Justo necesitaba esto!
alexchvrches
5

Robisz coś takiego:

{{ dateObj | date:'shortDate' }}

lub

{{ dateObj | date:'ddmmy' }}

Zobacz: https://angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html

Langley
źródło
przepraszam, jeśli nie było to jasne w moim pytaniu, ale właśnie to robię, ale ze wzorem „shortDate” i jest wyświetlane tylko w stylu amerykańskim. Styl czasu jest w porządku.
nsbm
Drugi przykład pokazuje format, który jest przekazywany do DatePipe, tego chciałeś, nie?
Langley
Próbowałem, ale to nie działa. Pokaż tylko cyfrę „5” niezależnie od daty.
nsbm
3

Zmagałem się z tym samym problemem i nie działałem, używając tego

{{dateObj | date:'ydM'}}

Próbowałem więc obejścia, nie najlepszego rozwiązania, ale zadziałało:

{{dateObj | date:'d'}}/{{dateObj | date:'M'}}/{{dateObj | date:'y'}}

Zawsze mogę stworzyć niestandardową rurę.

hydrangenius
źródło
3

Dla tych, którzy mają problemy z AOT, musisz zrobić to trochę inaczej z useFactory:

export function getCulture() {
    return 'fr-CA';
}

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: getCulture },
    //otherProviders...
  ]
})
vidalsasoon
źródło
4
od angular5 możesz użyć wyrażenia grubej strzałki w tablicy dostawców
iuliust
{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}
załatwił
0

Skopiowany potok Google zmienił ustawienia regionalne i działa w moim kraju, możliwe, że nie ukończyli go dla wszystkich lokalizacji. Poniżej znajduje się kod.

import {
    isDate,
    isNumber,
    isPresent,
    Date,
    DateWrapper,
    CONST,
    isBlank,
    FunctionWrapper
} from 'angular2/src/facade/lang';
import {DateFormatter} from 'angular2/src/facade/intl';
import {PipeTransform, WrappedValue, Pipe, Injectable} from 'angular2/core';
import {StringMapWrapper, ListWrapper} from 'angular2/src/facade/collection';


var defaultLocale: string = 'hr';

@CONST()
@Pipe({ name: 'mydate', pure: true })
@Injectable()
export class DatetimeTempPipe implements PipeTransform {
    /** @internal */
    static _ALIASES: { [key: string]: String } = {
        'medium': 'yMMMdjms',
        'short': 'yMdjm',
        'fullDate': 'yMMMMEEEEd',
        'longDate': 'yMMMMd',
        'mediumDate': 'yMMMd',
        'shortDate': 'yMd',
        'mediumTime': 'jms',
        'shortTime': 'jm'
    };


    transform(value: any, args: any[]): string {
        if (isBlank(value)) return null;

        if (!this.supports(value)) {
            console.log("DOES NOT SUPPORT THIS DUEYE ERROR");
        }

        var pattern: string = isPresent(args) && args.length > 0 ? args[0] : 'mediumDate';
        if (isNumber(value)) {
            value = DateWrapper.fromMillis(value);
        }
        if (StringMapWrapper.contains(DatetimeTempPipe._ALIASES, pattern)) {
            pattern = <string>StringMapWrapper.get(DatetimeTempPipe._ALIASES, pattern);
        }
        return DateFormatter.format(value, defaultLocale, pattern);
    }

    supports(obj: any): boolean { return isDate(obj) || isNumber(obj); }
}
Dživo Jelić
źródło
0

Ok, proponuję to rozwiązanie, bardzo proste, za pomocą ngx-translate

import { DatePipe } from '@angular/common';
import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '@ngx-translate/core';

@Pipe({
  name: 'localizedDate',
  pure: false
})
export class LocalizedDatePipe implements PipeTransform {

  constructor(private translateService: TranslateService) {
}

  transform(value: any): any {
    const date = new Date(value);

    const options = { weekday: 'long',
                  year: 'numeric',
                  month: 'long',
                  day: 'numeric',
                  hour: '2-digit',
                  minute: '2-digit',
                  second: '2-digit'
                    };

    return date.toLocaleString(this.translateService.currentLang, options);
  }

}
LizanLycan
źródło
-1

To może być trochę za późno, ale w moim przypadku (angular 6) utworzyłem prostą rurkę na górze DatePipe, coś takiego:

private _regionSub: Subscription;
private _localeId: string;

constructor(private _datePipe: DatePipe, private _store: Store<any>) {
  this._localeId = 'en-AU';
  this._regionSub = this._store.pipe(select(selectLocaleId))
    .subscribe((localeId: string) => {
      this._localeId = localeId || 'en-AU';
    });
}

ngOnDestroy() { // Unsubscribe }

transform(value: string | number, format?: string): string {
  const dateFormat = format || getLocaleDateFormat(this._localeId, FormatWidth.Short);
  return this._datePipe.transform(value, dateFormat, undefined, this._localeId);
}

Może nie jest to najlepsze rozwiązanie, ale proste i działa.

Ngoc Nam Nguyen
źródło