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