web-dev-qa-db-fra.com

jour incorrect dans angular sélecteur de date matériel

Lorsque je sélectionne une date, je vois la date correcte dans le champ mais, lorsque j'enregistre, le sélecteur de date envoie la veille de la date que j'ai sélectionnée (décalage de 3 heures) j'utilise angular forme réactive et MatMomentDateModule pour le sélecteur de date.

le problème est lié aux fuseaux horaires mais je veux juste enregistrer la même date que celle entrée par l'utilisateur dans la base de données.

Code reproduit ici: https://stackblitz.com/edit/angular-material-moment-adapter-example-kdk9nk?file=app%2Fapp.module.ts

issue on stackblitz

problème lié à cela sur githup:

https://github.com/angular/material2/issues/7167

Toute aide est appréciée, et je pense que beaucoup de développeurs ont besoin d'une solution pour cela.

15
Motaz Homsi

Il y a deux jours, à https://github.com/angular/material2/issues/7167 , Silthus a publié sa solution de contournement qui remplace le MomentJsDataAdapter. Je l'ai essayé et cela a fonctionné comme un charme de n'importe où dans le monde.

Il a d'abord ajouté un MomentUtcDateAdapter qui étend MomentDateAdapter

import { Inject, Injectable, Optional } from '@angular/core';
import { MAT_DATE_LOCALE } from '@angular/material';   
import { MomentDateAdapter } from '@angular/material-moment-adapter';
import { Moment } from 'moment';
import * as moment from 'moment';

@Injectable()
export class MomentUtcDateAdapter extends MomentDateAdapter {

  constructor(@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string) {
    super(dateLocale);
  }

  createDate(year: number, month: number, date: number): Moment {
    // Moment.js will create an invalid date if any of the components are out of bounds, but we
    // explicitly check each case so we can throw more descriptive errors.
    if (month < 0 || month > 11) {
      throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`);
    }

    if (date < 1) {
      throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
    }

    let result = moment.utc({ year, month, date }).locale(this.locale);

    // If the result isn't valid, the date must have been out of bounds for this month.
    if (!result.isValid()) {
      throw Error(`Invalid date "${date}" for month with index "${month}".`);
    }

    return result;
  }
}

Et puis dans le composant AppModule, vous devez faire ceci:

providers: [
    ...
    { provide: MAT_DATE_LOCALE, useValue: 'en-GB' },
    { provide: MAT_DATE_FORMATS, useValue: MAT_MOMENT_DATE_FORMATS },
    { provide: DateAdapter, useClass: MomentUtcDateAdapter },
    ...
],
20
Bruno Cerecetto

Ce sera peut-être utile pour quelqu'un. C'est mon exemple de méthode dans laquelle j'efface TimeZone OffSet de la date du composant

  addPriceListPeriod(priceListId: number, periodDateFrom: Date) {

    let UTCDate = Date.UTC(periodDateFrom.getFullYear(), periodDateFrom.getMonth(), periodDateFrom.getDate()) - periodDateFrom.getTimezoneOffset();

    periodDateFrom = new Date(UTCDate);

    const tempObject = {
      priceListId,
      fromDate: periodDateFrom
    }
    return this.httpClient.post('PriceLists/addPriceListPeriod', tempObject);
  }
1
Wzorzec

OPTION 1: A eu le même problème et l'a résolu en support (Java) Pouvez-vous résoudre ce problème dans votre code backend.
Présentation de Java au cas où quelqu'un aurait besoin de la même aide. Le concept devrait être similaire pour les autres technologies côté serveur également.

Simulé le même bug et voici l'analyse.

IMPRIMER Via JSON | "date de début": "2018-02-08T18: 30: 00.000Z".

IMPRIMER AVANT DE SOUMETTRE >> Ven 09 Fév 2018 00:00:00 GMT + 0530 (IST)

public static String dateConversion(String dt) {

        Instant timestamp = Instant.parse(dt);
        ZonedDateTime isttime = timestamp.atZone(ZoneId.of("Asia/Kolkata"));
        System.out.println(isttime);

        System.out.println(DateTimeFormatter.ofPattern("dd-MM-yyyy").format(isttime));
        return DateTimeFormatter.ofPattern("dd-MM-yyyy").format(isttime);
    }

OPTION 2: (solution en frontend) Je n'ai pas essayé cette option mais la documentation semble très claire.
https://maggiepint.com/2016/05/14/moment-js-shows-the-wrong-date/ Vérifiez cela.

1
Sivadinesh

https://github.com/angular/material2/issues/7167#issuecomment-402061126

Vous pouvez modifier le comportement par défaut pour analyser les dates au format UTC en fournissant MAT_MOMENT_DATA_ADAPTER_OPTIONS et en le définissant sur useUtc: true.

@NgModule({ 
    imports: [MatDatepickerModule, MatMomentDateModule], 
    providers: [ 
        { provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } } 
    ] 
})
1
Küzdi Máté

Le sélecteur de date de matériau angulaire ne prend pas en charge différents fuseaux horaires pour le moment et il vous donne un décalage horaire UTC. Mais pour moi, ce n'est pas un problème car j'enregistre la chaîne de sortie dans ma base de données et lorsque je la renvoie à l'utilisateur, le navigateur affiche l'objet date-heure correct. Essayez ceci dans votre console (im dans la zone +01) et vous verrez la date sélectionnée:

new Date('2018-02-08T23:00:00.000Z')
Fri Feb 09 2018 00:00:00 GMT+0100 (CET)

Une autre solution consiste à modifier votre objet date avant de l'enregistrer dans la base de données, ce qui n'est pas la meilleure pratique.

Enfin, si vous utilisez Moment.js dans votre application, vous pouvez essayer le MomentDateAdapter et voir si cela vous aide. Ajoutez simplement le MatMomentDateModule à votre application comme décrit ici .

1
pouyada

Utilisez simplement l'option useUtc: true pour MatMomentDateAdapter:

import { MatMomentDateModule, MAT_MOMENT_DATE_ADAPTER_OPTIONS } from '@angular/material-moment-adapter';

@NgModule({
  exports: [
    MatMomentDateModule,
    // ...
  ],
  providers: [
    { provide: MAT_MOMENT_DATE_ADAPTER_OPTIONS, useValue: { useUtc: true } }
  ],
})
export class MaterialModule { }
0
Interloper

merci à @ ankit-raonka de répondre ici: https://stackoverflow.com/a/48761312/6423656

l'utilisation de ControlValueAccessor a résolu mon problème et voici un exemple de travail: https://stackblitz.com/edit/angular-dlxnmx?file=app%2Fcva-date.component.ts

Merci pour tout le monde pour les réponses, je pense que ce problème pourrait également être résolu en utilisant la méthode d'analyse de l'adaptateur de date de moment, mais j'aime le ControlValueAccessor essayer car je contrôle tous les aspects d'entrée + réduire le code écrit quand je veux l'utiliser dans mon html.

0
Motaz Homsi