如何从 Angular 2 为 DatePicker 设置时区?

Mig*_*ias 6 angular-material angular-material2 angular

有没有办法从角度材料 2 在日期选择器上设置时区?

成分:

  <mat-form-field>
    <input matInput [matDatepicker]="picker" placeholder="Choose a date">
    <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
    <mat-datepicker #picker></mat-datepicker>
  </mat-form-field>
Run Code Online (Sandbox Code Playgroud)

Yan*_*lla 7

要在日期选择器上设置时区,您需要创建一个自定义 DateAdapter,如 @lee-richardson 提到的。

以下实现适用于 Angular 11.0.0。

https://stackblitz.com/edit/angular-zbmhw5-n955ki

我是如何创建这个 stackblitz 的:

  1. 我分叉了 Angular Material 文档提供的 stackblitz,说明了基本的日期选择器

  2. 我安装了时刻时区依赖项

  3. 我创建了一个 custom-moment-date-adapter.ts 并继承自Angular/Component 提供的MomentDateAdapter 。然后我重写了createDatedeserializeparsetoday方法。

例如,我对时区进行了硬编码,但您可以调整代码以从您喜欢的位置获取时区。

import { Inject, Injectable, Optional } from "@angular/core";
import { MomentDateAdapter } from "@angular/material-moment-adapter";
import { MAT_DATE_LOCALE } from "@angular/material/core";
import moment from "moment-timezone";

@Injectable()
export class CustomMomentDateAdapter extends MomentDateAdapter {
  constructor(@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string) {
    super(dateLocale);
  }

  static TIMEZONE = "Asia/Sakhalin";

  createDate(year: number, month: number, date: number): moment.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.`);
    }

    const monthString = ("0" + (month + 1)).slice(-2);
    const yearSting = ("0" + date).slice(-2);
    const dateString = `${year}-${monthString}-${yearSting} 00:00`;
    const result = moment.tz(dateString, CustomMomentDateAdapter.TIMEZONE);

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

  /**
   * Returns the given value if given a valid Moment or null. Deserializes valid ISO 8601 strings
   * (https://www.ietf.org/rfc/rfc3339.txt) and valid Date objects into valid Moments and empty
   * string into null. Returns an invalid date for all other values.
   */
  deserialize(value: any): moment.Moment | null {
    let date;
    if (value instanceof Date) {
      date = this._createMoment2(value).locale(this.locale);
    } else if (this.isDateInstance(value)) {
      // Note: assumes that cloning also sets the correct locale.
      return this.clone(value);
    }
    if (typeof value === "string") {
      if (!value) {
        return null;
      }
      date = this._createMoment2(value, moment.ISO_8601).locale(this.locale);
    }
    if (date && this.isValid(date)) {
      return this._createMoment2(date).locale(this.locale);
    }
    return super.deserialize(value);
  }

  parse(value: any, parseFormat: string | string[]): moment.Moment | null {
    if (value && typeof value === "string") {
      return this._createMoment2(value, parseFormat, this.locale);
    }
    return value ? this._createMoment2(value).locale(this.locale) : null;
  }

  today(): moment.Moment {
    return moment()
      .utc()
      .tz(CustomMomentDateAdapter.TIMEZONE)
      .local(this.locale);
  }

  /** Creates a Moment instance while respecting the current UTC settings. */
  private _createMoment2(
    date: moment.MomentInput,
    format?: moment.MomentFormatSpecification,
    locale?: string
  ): moment.Moment {
    const date2 = moment(date, format, locale).format("YYYY-MM-DD");
    return moment.tz(date2, CustomMomentDateAdapter.TIMEZONE);
  }
}
Run Code Online (Sandbox Code Playgroud)
  1. 在模块中(我的 stackblitz 示例中的 DemoMaterialModule): 2.1)我导入MatMomentDateModule 2.2)我注入了新创建的CustomMomentDateAdapter
providers: [{ provide: DateAdapter, useClass: CustomMomentDateAdapter }]
Run Code Online (Sandbox Code Playgroud)
  1. datepicker-overview-example为了这个示例的目的,我更新了组件。

我用来找到此解决方案的其他参考文献:


Edr*_*ric 0

您指的是语言环境吗?您必须使用MAT_DATE_LOCALEAngular Material 中的令牌来设置它。来自文档:

默认情况下,注入令牌MAT_DATE_LOCALE将使用. 如果您想覆盖它,您可以为令牌提供一个新值:LOCALE_ID@angular/coreMAT_DATE_LOCALE

@NgModule({
    providers: [
        {provide: MAT_DATE_LOCALE, useValue: 'en-GB'},
    ],
})
export class MyApp {}
Run Code Online (Sandbox Code Playgroud)

还可以使用setLocale.DateAdapter

import { DateAdapter, NativeDateAdapter } from '@angular/material';

@Component({
    selector: 'foo',
    template: ''
})
export class FooComponent {
    constructor(dateAdapter: DateAdapter<NativeDateAdapter>) {
        dateAdapter.setLocale('de-DE');
    }
}
Run Code Online (Sandbox Code Playgroud)