web-dev-qa-db-ja.com

angular material datepickerでの日付が正しくありません

日付を選択するとフィールドに正しい日付が表示されますが、保存すると、日付ピッカーは選択した日付の前日を送信します(3時間オフセット)angular反応型日付ピッカーのMatMomentDateModule。

問題はタイムゾーンに関連していますが、ユーザーがデータベースに入力した日付と同じ日付を保存したいだけです。

ここでコードを還元: https://stackblitz.com/edit/angular-material-moment-adapter-example-kdk9nk?file=app%2Fapp.module.ts

issue on stackblitz

githupでこれに関連する問題:

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

どんな助けも感謝します、そして、私は多くの開発者がこのための解決策を必要とすると思います。

15
Motaz Homsi

2日前、 https://github.com/angular/material2/issues/7167 で、SilthusはMomentJsD​​ataAdapterをオーバーライドする回避策を投稿しました。私はそれを試してみましたが、それは世界中のどこからでも魅力として働きました。

まず、MomentDateAdapterを拡張するMomentUtcDateAdapterを追加しました

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

そして、AppModuleコンポーネントで、これを行う必要があります。

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

たぶんそれは誰かに役立つでしょう。これは、コンポーネントの日付からTimeZone OffSetを消去する方法の例です

  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

オプション1:同じ問題があり、バックで解決しました(Java)バックエンドコードでこれを解決できますか。
Presenting Java誰かが同じヘルプを必要とする場合のコード。概念は他のサーバー側のテクノロジーでも同様でなければなりません。

同じバグをシミュレートし、以下が分析です。

JSONで印刷| 「開始日」:「2018-02-08T18:30:00.000Z」.

送信前に印刷>> 2018年2月9日金曜日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);
    }

オプション2:(フロントエンドの解決策)このオプションは試していませんが、ドキュメントは非常に明確です。
https://maggiepint.com/2016/05/14/moment-js-shows-the-wrong-date/ これをチェックしてください。

1
Sivadinesh

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

MAT_MOMENT_DATA_ADAPTER_OPTIONSを指定してuseUtc:trueに設定することにより、日付をUTCとして解析するデフォルトの動作を変更できます。

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

角度材料の日付ピッカーは、現時点では異なるタイムゾーンをサポートしておらず、UTC時間オフセットを提供します。しかし、私にとっては、出力文字列をデータベースに保存し、ユーザーに返すと、ブラウザに正しい日付時刻オブジェクトが表示されるため、問題はありません。コンソールでこれを試してください(+01ゾーンでim)、選択した日付が表示されます:

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

別の解決策は、データベースに保存する前に日付オブジェクトを変更することです。これはベストプラクティスではありません。

最後に、アプリでMoment.jsを使用している場合は、MomentDateAdapterを試して、それが役立つかどうかを確認できます。 here の説明に従って、アプリケーションにMatMomentDateModuleを追加するだけです。

1
pouyada

MatMomentDateAdapterにはオプションuseUtc: trueを使用します。

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

ここに@ ankit-raonkaの答えのおかげで: https://stackoverflow.com/a/48761312/6423656

controlValueAccessorを使用することで問題が解決しました。次に例を示します。 https://stackblitz.com/edit/angular-dlxnmx?file=app%2Fcva-date.component.ts

答えてくれたすべての人に感謝します。この問題はモーメント日付アダプターの解析方法を使用しても解決できると思いますが、ControlValueAccessorのように、すべての入力側面を制御し、htmlで使用したいときに書かれたコードを減らしてください。

0
Motaz Homsi