Comment définir les paramètres régionaux dans DatePipe dans Angular 2?

138

Je veux Affichage de la date en utilisant le format européen dd/MM/yyyymais en utilisant DatePipe shortDate formatez afficher uniquement en utilisant le style de la date des États - Unis MM/dd/yyyy.
Je suppose que la locale par défaut est en_US. Peut-être que je manque dans la documentation, mais comment puis-je modifier les paramètres régionaux par défaut dans une application Angular2? Ou peut-être existe-t-il un moyen de transmettre un format personnalisé à DatePipe?

nsbm
la source
1
J'aimerais savoir ça aussi. J'ai trouvé que les documents sur le tuyau de date qui expliquent l'ordre des y m 'et des d dans la chaîne de format sont ignorés car l'ordre est défini par les paramètres régionaux. Mais aucune indication sur la façon de définir (ou même d'obtenir) les paramètres régionaux.
Mark Farmiloe

Réponses:

276

À partir d'Angular2 RC6, vous pouvez définir les paramètres régionaux par défaut dans votre module d'application, en ajoutant un fournisseur:

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

Les tubes Devise / Date / Nombre doivent sélectionner les paramètres régionaux. LOCALE_ID est un OpaqueToken , à importer depuis angular / core.

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

Pour un cas d'utilisation plus avancé, vous souhaiterez peut-être récupérer les paramètres régionaux d'un service. Les paramètres régionaux seront résolus (une fois) lorsque le composant utilisant le tube de date est créé:

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

J'espère que ça marche pour toi.

corolle
la source
43
Je suis étonné que cela ne semble toujours pas être documenté. Pas sur la page Date Pipe ( angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html ), pas sur la page générale des pipes ( angular.io/docs/ts/latest/guide/pipes .html ) et cette question est en fait le premier appel sur Google ( google.com/search?q=angular%202%20locales&rct=j ). Super trouvaille.
JP ten Berge
2
Pour utiliser un tube dans le code, vous devez maintenant le formater comme new CurrencyPipe('en-US');. J'espère que cela sera utile pour quelque chose, car cela est apparu comme le premier résultat lors de la recherche de mon problème sur Google.
Ash Blue
1
@corolla Pouvez-vous nous éclairer sur ce service? Je souhaite modifier les paramètres régionaux lorsque l'application est en cours d'exécution, est-ce possible avec ce service? Et comment mettre en œuvre un tel service?
Martijn van den Bergh
1
@MartijnvandenBergh, le service renvoie simplement une chaîne de paramètres régionaux - rien d'extraordinaire. Nous avons eu des résultats mitigés en essayant de changer les paramètres régionaux pendant l'exécution de l'application. Fin de la page de rechargement pour gérer tous les cas. YMMV.
corolla
1
J'ai aussi beaucoup lutté avec ce sujet et j'espère que l'article que j'ai écrit à ce sujet pourra aider certaines personnes: medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
Michael Karén
72

La solution avec LOCALE_ID est idéale si vous souhaitez définir une fois la langue de votre application. Mais cela ne fonctionne pas, si vous souhaitez changer la langue pendant l'exécution. Dans ce cas, vous pouvez implémenter un canal de date personnalisé.

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

}

Maintenant, si vous changez la langue d'affichage de l'application à l'aide de TranslateService (voir ngx-translate )

this.translateService.use('en');

les formats de votre application doivent être automatiquement mis à jour.

Exemple d'utilisation:

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

ou consultez mon projet "Notes" simple ici .

entrez la description de l'image ici

Milan Hlinák
la source
J'obtiens une erreur d'analyse de modèle; impossible de compiler le filtre 'localizedDate' que j'ai utilisé de la même manière que suggéré.
Prasad Shinde
Avez-vous correctement déclaré LocalizedDatePipe? Voir pipe.module.ts dans mon exemple de projet .
Milan Hlinák le
Oui, je l'ai résolu plus tôt, @Milan Hlinak j'aurais dû répondre à mon commentaire à ce moment-là seulement. Mais de toute façon merci pour votre réponse rapide. Tu le fais bien.
Prasad Shinde
C'est apparemment ce que je cherchais. C'est dommage qu'un tube personnalisé soit nécessaire pour changer simplement les
paramètres
2
Ca marche mais attention, utiliser une pipe "impure" est plus lente que la "pure". Comme le dit le guide angulaire : Angular exécute un tuyau impur à chaque cycle de détection de changement de composant. Un tuyau impur est souvent appelé, aussi souvent que chaque frappe ou mouvement de souris. Avec cette préoccupation à l'esprit, installez une conduite impure avec beaucoup de soin. Un tuyau coûteux et de longue durée pourrait détruire l'expérience utilisateur.
Luca Ritossa
64

Avec angular5la réponse ci-dessus ne fonctionne plus!

Le code suivant:

app.module.ts

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

Conduit à l'erreur suivante:

Erreur: données locales manquantes pour les paramètres régionaux "de-at".

Avec, angular5vous devez charger et enregistrer vous-même le fichier de paramètres régionaux utilisé.

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

Documentation

zgue
la source
En effet, si vous avez besoin d'utiliser une autre locale sauf en-US, vous devez l'enregistrer. Merci pour la réponse, @zgue
MikkaRin
1
OK cela m'a empêché un autre mal de tête .. Thx! La doc est un peu compliquée, puisque je pensais que registerLocaleDatac'était suffisant, eh bien ce n'est pas le cas.
danger89
1
Meilleure réponse pour Ionic 4!
parrycima le
22

Si vous utilisez TranslateServicefrom @ngx-translate/core, vous trouverez ci-dessous une version sans créer de nouveau tube qui fonctionne avec la commutation dynamique à l'exécution (testé sur Angular 7). Utilisation de DatePipelocale paramètre ( docs ):

Tout d'abord, déclarez les paramètres régionaux que vous utilisez dans votre application, par exemple dans 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');
}

Ensuite, utilisez votre pipe dynamiquement:

myComponent.component.html

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

myComponent.component.ts

 constructor(public translateService: TranslateService) { ... }
knnhcn
la source
2
C'est étonnamment agréable. Vous n'avez même pas besoin de @ ngx-translate pour cela. Pouvez-vous expliquer ce que fait la déclaration dans le modèle?
lama
2
@lama, dueDate (toute date que vous souhaitez formater) | date: 'shortDate' (1er paramètre du tube de date correspondant à 'format') : '' (2ème paramètre => timeZone, "Lorsqu'il n'est pas fourni, utilise le fuseau horaire du système local de l'utilisateur final".) : trasnlateService.currentLang (3ème paramètre => local), poussin ce DatePipe
Diego Osornio
et si vous avez un format personnalisé? cela serait-il localisé aussi?
Wildhammer
12

J'ai jeté un œil dans date_pipe.ts et il contient deux informations intéressantes. près du haut se trouvent les deux lignes suivantes:

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

Près du bas se trouve cette ligne:

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

Cela me suggère que le tube de date est actuellement codé en dur pour être «en-US».

Veuillez m'éclairer si je me trompe.

Mark Farmiloe
la source
Vous voudrez peut-être consulter la réponse de corolla ci-dessous. Il est plus à jour et offre une excellente solution.
Mark Langer
9

Sur app.module.ts, ajoutez les importations suivantes. Il y a une liste d'options LOCALE ici .

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

Ajoutez ensuite le fournisseur

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

Utilisez des tuyaux en html. Voici la documentation angulaire pour cela.

{{ dateObject | date: 'medium' }}
Alejandro del Río
la source
Justo necesitaba esto!
alexchvrches le
5

Vous faites quelque chose comme ça:

{{ dateObj | date:'shortDate' }}

ou

{{ dateObj | date:'ddmmy' }}

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

Langley
la source
désolé si ce n'était pas clair dans ma question, mais c'est exactement ce que je fais mais avec le modèle 'shortDate' et cela ne s'affiche que dans le style américain. Le style du temps est bien.
nsbm
Le deuxième exemple montre un format passé au DatePipe, c'est ce que vous vouliez non?
Langley
Essayé mais ça ne marche pas. N'affichez que le chiffre «5» indépendamment de la date.
nsbm
3

Je luttais avec le même problème et je n'ai pas travaillé pour moi en utilisant ceci

{{dateObj | date:'ydM'}}

Donc, j'ai essayé une solution de contournement, pas la meilleure solution mais cela a fonctionné:

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

Je peux toujours créer un tuyau personnalisé.

hortensia
la source
3

Pour ceux qui ont des problèmes avec AOT, vous devez le faire un peu différemment avec une useFactory:

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

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: getCulture },
    //otherProviders...
  ]
})
vidalsasoon
la source
4
à partir de angular5, vous pouvez utiliser une expression de grosse flèche dans le tableau des fournisseurs
iuliust
{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}a fait l'affaire pour moi;)
JoxieMedina
0

Copié le tube google a changé les paramètres régionaux et cela fonctionne pour mon pays, il est possible qu'ils ne l'aient pas terminé pour tous les paramètres régionaux. Ci-dessous le 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ć
la source
0

Ok, je propose cette solution, très simple, utilisant 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
la source
-1

C'est peut-être un peu tard, mais dans mon cas (angulaire 6), j'ai créé un simple tuyau au-dessus de DatePipe, quelque chose comme ceci:

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

Peut-être pas la meilleure solution, mais simple et fonctionne.

Ngoc Nam Nguyen
la source