Wie setze ich das Gebietsschema in DatePipe in Angular 2?

137

Ich möchte das Datum im europäischen Format anzeigen, dd/MM/yyyyaber im DatePipe shortDate- Format wird es nur im US-Datumsstil angezeigt MM/dd/yyyy.
Ich gehe davon aus, dass das Standardgebietsschema en_US ist. Möglicherweise fehlt es mir in den Dokumenten, aber wie kann ich die Standardeinstellungen für das Gebietsschema in einer Angular2-App ändern? Oder gibt es eine Möglichkeit, ein benutzerdefiniertes Format an DatePipe zu übergeben?

nsbm
quelle
1
Das würde ich auch gerne wissen. Ich habe festgestellt, dass die Datums-Pipe-Dokumente, in denen die Reihenfolge der ys m 'und ds in der Formatzeichenfolge erläutert wird, ignoriert werden, da die Reihenfolge vom Gebietsschema festgelegt wird. Aber kein Hinweis darauf, wie das Gebietsschema festgelegt (oder sogar abgerufen) werden soll.
Mark Farmiloe

Antworten:

274

Ab Angular2 RC6 können Sie das Standardgebietsschema in Ihrem App-Modul festlegen, indem Sie einen Anbieter hinzufügen:

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

Die Pipes Currency / Date / Number sollten das Gebietsschema übernehmen. LOCALE_ID ist ein OpaqueToken , das aus Angular / Core importiert werden soll.

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

Für einen fortgeschritteneren Anwendungsfall möchten Sie möglicherweise das Gebietsschema von einem Dienst abrufen. Das Gebietsschema wird (einmal) aufgelöst, wenn eine Komponente mit Datums-Pipe erstellt wird:

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

Hoffe es funktioniert bei dir.

Blumenkrone
quelle
42
Ich bin erstaunt, dass dies immer noch nirgendwo dokumentiert zu sein scheint. Nicht auf der Seite "Date Pipe" ( angle.io/docs/ts/latest/api/common/index/DatePipe-pipe.html ), nicht auf der Seite "General Pipes" ( angle.io/docs/ts/latest/guide/pipes) .html ) und diese Frage ist tatsächlich der erste Treffer bei Google ( google.com/search?q=angular%202%20locales&rct=j ). Toller Fund.
JP Ten Berge
2
Um eine Pipe im Code zu verwenden, müssen Sie sie jetzt wie folgt formatieren new CurrencyPipe('en-US');. Hoffentlich ist dies für etwas nützlich, da dies als erstes Ergebnis beim Googeln meines Problems angezeigt wurde.
Ash Blue
1
@corolla Kannst du etwas Licht in diesen Service bringen? Ich möchte das Gebietsschema ändern, wenn die App ausgeführt wird. Ist das mit diesem Dienst möglich? Und wie würde ich einen solchen Service implementieren?
Martijn van den Bergh
1
@MartijnvandenBergh, der Dienst gibt nur die Gebietsschema-Zeichenfolge zurück - nichts Besonderes. Wir hatten gemischte Ergebnisse beim Versuch, das Gebietsschema zu ändern, während die App ausgeführt wird. Am Ende wurde die Seite neu geladen, um alle Fälle zu behandeln. YMMV.
Blumenkrone
1
Ich hatte auch große Probleme
Michael Karén
72

Die Lösung mit LOCALE_ID ist ideal, wenn Sie die Sprache für Ihre App einmal festlegen möchten. Aber es funktioniert nicht, wenn Sie die Sprache zur Laufzeit ändern möchten. In diesem Fall können Sie eine benutzerdefinierte Datums-Pipe implementieren.

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);
  }

}

Wenn Sie nun die App-Anzeigesprache mit TranslateService ändern (siehe ngx-translate )

this.translateService.use('en');

Die Formate in Ihrer App sollten automatisch aktualisiert werden.

Anwendungsbeispiel:

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

oder überprüfen Sie mein einfaches "Notizen" -Projekt hier .

Geben Sie hier die Bildbeschreibung ein

Milan Hlinák
quelle
Ich erhalte einen Fehler beim Analysieren der Vorlage. Der Filter 'localizedDate', den ich auf die gleiche Weise wie vorgeschlagen verwendet habe, kann nicht kompiliert werden.
Prasad Shinde
Haben Sie LocalizedDatePipe korrekt deklariert? Siehe pipe.module.ts in meinem Beispielprojekt .
Milan Hlinák
Ja, ich habe es früher gelöst, @Milan Hlinak Ich hätte nur zu diesem Zeitpunkt auf meinen Kommentar antworten sollen. Trotzdem danke für Ihre schnelle Antwort. Du machst das großartig.
Prasad Shinde
Dies ist anscheinend das, wonach ich gesucht habe. Es ist eine Schande, dass eine benutzerdefinierte Pipe erforderlich ist, um das Gebietsschema zur Laufzeit zu ändern.
dendimiiii
2
Es funktioniert, aber achten Sie darauf, dass die Verwendung eines "unreinen" Rohrs langsamer ist als das "reine". Wie Angular Guide sagt: Angular führt während jedes Zyklus zur Erkennung von Komponentenwechseln ein unreines Rohr aus. Ein unreines Rohr wird oft aufgerufen, so oft wie jeder Tastendruck oder jede Mausbewegung. Verwenden Sie vor diesem Hintergrund ein unreines Rohr mit großer Sorgfalt. Ein teures, lang laufendes Rohr kann die Benutzererfahrung beeinträchtigen.
Luca Ritossa
64

Mit angular5der obigen Antwort funktioniert das nicht mehr!

Der folgende Code:

app.module.ts

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

Führt zu folgendem Fehler:

Fehler: Fehlende Gebietsschemadaten für das Gebietsschema "de-at".

Mit müssen angular5Sie die verwendete Gebietsschemadatei selbst laden und registrieren.

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...
  ]
})

Dokumentation

zgue
quelle
Wenn Sie ein anderes Gebietsschema als en-US verwenden müssen, sollten Sie es registrieren. Vielen Dank für die Antwort, @zgue
MikkaRin
1
OK, das hat mir weitere Kopfschmerzen erspart. Danke! Das Dokument ist ein bisschen kompliziert, da ich dachte, dass registerLocaleDatadas genug war, nun, es ist nicht.
Gefahr89
1
Beste Antwort für Ionic 4!
Parrycima
22

Wenn Sie TranslateServicefrom verwenden @ngx-translate/core, finden Sie unten eine Version ohne Erstellen einer neuen Pipe, die mit dynamischem Umschalten zur Laufzeit arbeitet (getestet in Angular 7). Verwenden des DatePipe- localeParameters ( docs ):

Deklarieren Sie zunächst die Gebietsschemas, die Sie in Ihrer App verwenden, z. B 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');
}

Verwenden Sie dann Ihre Pfeife dynamisch:

myComponent.component.html

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

myComponent.component.ts

 constructor(public translateService: TranslateService) { ... }
knnhcn
quelle
2
Das ist überraschend schön. Sie brauchen dafür nicht einmal @ ngx-translate. Können Sie erklären, was die Anweisung in der Vorlage bewirkt?
Lama
2
@lama, dueDate (jedes Datum, das Sie formatieren möchten) | Datum: 'shortDate' (1. Parameter für Datumspipe entsprechend 'Format') : '' (2. Parameter => Zeitzone, "Wenn nicht angegeben, verwendet die lokale Systemzeitzone des Endbenutzers".) : trasnlateService.currentLang (3. Parameter => local), Küken Sie diese DatePipe
Diego Osornio
Was ist, wenn Sie das Format angepasst haben? Wäre das auch lokalisiert?
Wildhammer
12

Ich habe in date_pipe.ts nachgesehen und es enthält zwei interessante Informationen. In der Nähe der Oberseite befinden sich die folgenden zwei Zeilen:

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

Ganz unten steht diese Zeile:

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

Dies deutet darauf hin, dass die Datumspipe derzeit fest codiert ist, um "en-US" zu sein.

Bitte klären Sie mich auf, wenn ich falsch liege.

Mark Farmiloe
quelle
Vielleicht möchten Sie die Antwort von Corolla unten lesen. Es ist aktueller und bietet eine großartige Lösung.
Mark Langer
9

Fügen Sie auf app.module.ts die folgenden Importe hinzu. Es gibt eine Liste von LOCALE Optionen hier .

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

Fügen Sie dann den Anbieter hinzu

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

Verwenden Sie Pipes in HTML. Hier ist die eckige Dokumentation dazu.

{{ dateObject | date: 'medium' }}
Alejandro del Río
quelle
Justo necesitaba esto!
Alexchvrches
5

Du machst so etwas:

{{ dateObj | date:'shortDate' }}

oder

{{ dateObj | date:'ddmmy' }}

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

Langley
quelle
Es tut mir leid, wenn es in meiner Frage nicht klar war, aber genau das mache ich, aber mit dem Muster 'shortDate' und es wird nur im US-Stil angezeigt. Der Zeitstil ist in Ordnung.
nsbm
Das zweite Beispiel zeigt ein Format, das an die DatePipe übergeben wird. Wollten Sie das nicht?
Langley
Versucht, aber es funktioniert nicht. Zeigen Sie unabhängig vom Datum nur die Zahl '5' an.
nsbm
3

Ich hatte mit dem gleichen Problem zu kämpfen und arbeitete nicht für mich damit

{{dateObj | date:'ydM'}}

Also habe ich eine Problemumgehung versucht, nicht die beste Lösung, aber es hat funktioniert:

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

Ich kann immer eine benutzerdefinierte Pipe erstellen.

Hydrangenius
quelle
3

Für diejenigen, die Probleme mit AOT haben, müssen Sie es mit einer useFactory etwas anders machen:

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

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: getCulture },
    //otherProviders...
  ]
})
vidalsasoon
quelle
4
Ab Angular5 können Sie einen Fettpfeil-Ausdruck im Provider-Array verwenden
iuliust
{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}hat den Trick für mich gemacht;)
JoxieMedina
0

Durch das Kopieren der Google-Pipe wurde das Gebietsschema geändert und es funktioniert für mein Land. Es ist möglich, dass sie es nicht für alle Gebietsschemas fertiggestellt haben. Unten ist der Code.

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ć
quelle
0

Ok, ich schlage diese Lösung vor, sehr einfach, mit 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
quelle
-1

Dies mag etwas spät sein, aber in meinem Fall (Winkel 6) habe ich eine einfache Pipe über DatePipe erstellt, ungefähr so:

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);
}

Vielleicht nicht die beste Lösung, aber einfach und funktioniert.

Ngoc Nam Nguyen
quelle