Come impostare le impostazioni internazionali in DatePipe in Angular 2?


138

Voglio visualizzare la data usando il formato europeo, dd/MM/yyyyma usando il formato DatePipe shortDate viene visualizzato solo usando lo stile della data USA MM/dd/yyyy.
Suppongo che l'impostazione internazionale predefinita sia en_US. Forse mi manca la documentazione, ma come posso modificare le impostazioni internazionali predefinite in un'app Angular2? O forse c'è un modo per passare un formato personalizzato a DatePipe?


1
Vorrei sapere anche questo. Ho trovato i documenti della pipe della data che spiegano l'ordine delle lettere y 'm' e 'd nella stringa di formato vengono ignorati quando l'ordine è impostato dalla locale. Ma nessuna indicazione su come impostare (o persino ottenere) le impostazioni internazionali.
Mark Farmiloe,

Risposte:


276

A partire da Angular2 RC6, è possibile impostare le impostazioni internazionali predefinite nel modulo dell'app, aggiungendo un provider:

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

Le pipe Valuta / Data / Numero dovrebbero selezionare le impostazioni internazionali. LOCALE_ID è un OpaqueToken , da importare da angolare / centrale.

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

Per un caso d'uso più avanzato, potresti voler ritirare le impostazioni locali da un servizio. Le impostazioni internazionali verranno risolte (una volta) quando viene creato il componente che utilizza la pipe di data:

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

Spero che funzioni per te.


43
Sono sorpreso che questo non sembra essere documentato da nessuna parte. Non sulla pagina della pipe di data ( angular.io/docs/ts/latest/api/common/index/DatePipe-pipe.html ), non sulla pagina delle pipe generali ( angular.io/docs/ts/latest/guide/pipes .html ) e questa domanda è in realtà il primo successo su Google ( google.com/search?q=angular%202%20locales&rct=j ). Grande scoperta.
JP dieci Berge,

2
Per usare una pipe nel codice ora è necessario formattarlo come new CurrencyPipe('en-US');. Spero che questo sia utile per qualcosa come questo si è rivelato come il primo risultato quando ho cercato su Google il mio problema.
Ash Blue,

1
@corolla Puoi far luce su quel servizio? Vorrei cambiare le impostazioni locali quando l'app è in esecuzione, è possibile con quel servizio? E come implementerei tale servizio?
Martijn van den Bergh,

1
@MartijnvandenBergh, il servizio restituisce solo una stringa locale - niente di speciale. Abbiamo avuto risultati contrastanti nel tentativo di cambiare le impostazioni locali durante l'esecuzione dell'app. Ho finito per ricaricare la pagina per gestire tutti i casi. YMMV.
corolla,

1
Ho anche lottato molto con questo argomento e spero che l'articolo che ho scritto su questo possa aiutare alcune persone: medium.com/dailyjs/dynamic-locales-in-angular-dd9a527ebe1f
Michael Karén

72

La soluzione con LOCALE_ID è ottima se vuoi impostare la lingua per la tua app una volta. Ma non funziona, se vuoi cambiare la lingua durante il runtime. In questo caso è possibile implementare la pipe della data personalizzata.

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

}

Ora se cambi la lingua di visualizzazione dell'app usando TranslateService (vedi ngx-translate )

this.translateService.use('en');

i formati all'interno dell'app dovrebbero essere aggiornati automaticamente.

Esempio di utilizzo:

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

o controllare le mie semplici "Note" del progetto qui .

inserisci qui la descrizione dell'immagine


Ricevo un errore di analisi del modello; impossibile compilare il filtro 'localizedDate' che ho usato allo stesso modo suggerito.
Prasad Shinde,

Hai dichiarato LocalizedDatePipe correttamente? Vedi pipe.module.ts nel mio progetto di esempio .
Milan Hlinák,

Sì, l'ho risolto in precedenza, @Milan Hlinak avrei dovuto rispondere al mio commento solo in quel momento. Ma comunque grazie per la tua pronta risposta. Stai andando alla grande.
Prasad Shinde,

Questo è apparentemente quello che stavo cercando. È un peccato che sia necessaria una pipe personalizzata per cambiare Locale in fase di runtime però ...
dendimiiii

2
Funziona ma presta attenzione al fatto che usare un tubo "impuro" è più lento del "puro". Come dice la guida angolare : Angular esegue un tubo impuro durante ogni ciclo di rilevamento del cambio di componente. Una pipe impura viene chiamata spesso, ogni volta che si preme un tasto o una mossa del mouse. Con questa preoccupazione in mente, implementa una pipa impura con grande cura. Un tubo costoso e di lunga durata potrebbe distruggere l'esperienza dell'utente.
Luca Ritossa,

64

Con angular5la risposta sopra non funziona più!

Il seguente codice:

app.module.ts

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

Porta al seguente errore:

Errore: dati locali mancanti per la locale "de-at".

Con angular5devi caricare e registrare il file locale usato da solo.

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

Documentazione


In effetti, se è necessario utilizzare altre impostazioni internazionali ad eccezione di en-US, è necessario registrarlo. Grazie per la risposta, @zgue
MikkaRin

1
OK, mi ha impedito un altro mal di testa .. Grazie! Il documento è un po 'complicato, dal momento che ho pensato che registerLocaleDatafosse abbastanza, beh non lo è.
danger89,

1
Migliore risposta per Ionic 4!
Parrycima,

22

Se usi TranslateServiceda @ngx-translate/core, di seguito è una versione senza creare una nuova pipe che funziona con la commutazione dinamica in fase di esecuzione (testata su Angular 7). Usando il localeparametro ( documenti ) di DatePipe :

Per prima cosa, dichiara le impostazioni locali che usi nella tua app, ad esempio in 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');
}

Quindi, utilizza la pipa in modo dinamico:

myComponent.component.html

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

myComponent.component.ts

 constructor(public translateService: TranslateService) { ... }

2
Questo è sorprendentemente bello. Non hai nemmeno bisogno di @ ngx-translate per questo. Puoi spiegarci cosa fa l'istruzione nel modello?
lama

2
@lama, dueDate (qualsiasi data che desideri formattare) | data: 'shortDate' (primo parametro per la data pipe corrispondente a 'formato') : '' (secondo parametro => timeZone, "Se non fornito, utilizza il fuso orario del sistema locale dell'utente finale".) : trasnlateService.currentLang (terzo parametro => locale), pulisci
Diego Osornio

cosa succede se hai un formato personalizzato? sarebbe anche localizzato?
Wildhammer

12

Ho dato un'occhiata a date_pipe.ts e ha due bit di informazioni che sono interessanti. vicino alla cima ci sono le seguenti due linee:

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

In fondo c'è questa linea:

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

Questo mi suggerisce che la data pipe sia attualmente codificata per essere "en-US".

Per favore, illuminami se sbaglio.



Potresti voler dare un'occhiata alla risposta della corolla qui sotto. È più aggiornato e offre un'ottima soluzione.
Mark Langer,

9

Su app.module.ts aggiungi le seguenti importazioni. C'è un elenco di opzioni LOCALE qui .

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

Quindi aggiungere il provider

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

Usa le pipe in html. Ecco la documentazione angolare per questo.

{{ dateObject | date: 'medium' }}

Justo necesitaba esto!
alexchvrches,

5

Fai qualcosa del genere:

{{ dateObj | date:'shortDate' }}

o

{{ dateObj | date:'ddmmy' }}

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


scusate se non è stato chiaro nella mia domanda, ma questo è esattamente quello che sto facendo, ma con il modello 'shortDate' e mostra solo in stile americano. Lo stile del tempo va bene.
nsbm,

Il secondo esempio mostra un formato che viene passato al DatePipe, questo è quello che volevi no?
Langley,

Ho provato ma non funziona. Mostra solo il numero '5' indipendentemente dalla data.
nsbm,

3

Ero alle prese con lo stesso problema e non ho funzionato per me usando questo

{{dateObj | date:'ydM'}}

Quindi, ho provato una soluzione alternativa, non la soluzione migliore ma ha funzionato:

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

Posso sempre creare una pipe personalizzata.


3

Per coloro che hanno problemi con AOT, è necessario farlo in modo leggermente diverso con un useFactory:

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

@NgModule({
  providers: [
    { provide: LOCALE_ID, useFactory: getCulture },
    //otherProviders...
  ]
})

4
a partire da angular5, puoi usare un'espressione di freccia
grossa

{ provide: LOCALE_ID, useFactory: () => 'fr-CA'}ha fatto il trucco per me;)
Joxie Medina il

0

Copiato il pipe di Google ha cambiato le impostazioni locali e funziona per il mio paese, è possibile che non lo abbiano finito per tutte le versioni locali. Di seguito è riportato il codice.

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

0

Ok, propongo questa soluzione, molto semplice, usando 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);
  }

}

-1

Potrebbe essere un po 'tardi, ma nel mio caso (angolare 6), ho creato una semplice pipe in cima a DatePipe, qualcosa del genere:

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

Potrebbe non essere la soluzione migliore, ma semplice e funzionante.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.