如何为angular-material-components/datetime-picker设置非UTC时区格式?
解决angular-material-components日期选择器显示本地时区缩写的问题
要实现Feb 10, 2024, 06:00 PM CST这种带本地时区缩写的显示效果,确实需要自定义日期适配器——不管是基于NgxMatNativeDateModule还是NgxMatMomentModule,默认适配器都无法直接满足显示时区缩写的需求。下面提供两种可行方案:
方案一:基于NgxMatMomentModule自定义适配器
借助moment-timezone扩展moment的时区处理能力,覆盖默认适配器的格式化方法来显示时区缩写:
- 确保依赖安装(若未安装):
npm install moment-timezone
- 创建自定义适配器文件(比如
custom-moment-datetime-adapter.ts):
import { Injectable } from '@angular/core'; import { NgxMatMomentDatetimeAdapter } from '@angular-material-components/datetime-picker'; import * as moment from 'moment-timezone'; @Injectable() export class CustomMomentDatetimeAdapter extends NgxMatMomentDatetimeAdapter { format(date: moment.Moment, displayFormat: string): string { // 检查格式是否包含时区缩写占位符 if (displayFormat.includes('z') || displayFormat.includes('zz')) { // 自动识别本地时区并获取缩写 const localTzAbbr = moment.tz.guess(true); // 基于本地时区格式化日期 return date.tz(localTzAbbr).format(displayFormat); } return super.format(date, displayFormat); } }
- 在模块中配置自定义适配器与格式:
import { NgModule } from '@angular/core'; import { NgxMatDatetimePickerModule, NgxMatTimepickerModule, NGX_MAT_DATETIME_FORMATS, NgxMatMomentDatetimeAdapter, NGX_MAT_MOMENT_DATETIME_ADAPTER_OPTIONS } from '@angular-material-components/datetime-picker'; import { CustomMomentDatetimeAdapter } from './custom-moment-datetime-adapter'; // 定义目标格式,z代表时区缩写 export const CUSTOM_DATETIME_FORMATS = { parse: { dateInput: 'MMM D, YYYY, hh:mm A z', }, display: { dateInput: 'MMM D, YYYY, hh:mm A z', // 对应需求的显示格式 monthYearLabel: 'MMM YYYY', dateA11yLabel: 'LL', monthYearA11yLabel: 'MMMM YYYY', }, }; @NgModule({ imports: [NgxMatDatetimePickerModule, NgxMatTimepickerModule], providers: [ { provide: NgxMatMomentDatetimeAdapter, useClass: CustomMomentDatetimeAdapter, deps: [NGX_MAT_MOMENT_DATETIME_ADAPTER_OPTIONS] }, { provide: NGX_MAT_DATETIME_FORMATS, useValue: CUSTOM_DATETIME_FORMATS } ] }) export class DatetimePickerConfigModule { }
方案二:基于NgxMatNativeDateModule自定义适配器
如果不想依赖moment,可扩展原生Date适配器,手动提取时区缩写:
- 创建自定义原生适配器文件(
custom-native-datetime-adapter.ts):
import { Injectable } from '@angular/core'; import { NgxMatNativeDatetimeAdapter } from '@angular-material-components/datetime-picker'; import { formatDate } from '@angular/common'; @Injectable() export class CustomNativeDatetimeAdapter extends NgxMatNativeDatetimeAdapter { format(date: Date, displayFormat: string): string { if (displayFormat.includes('z')) { // 先格式化基础日期部分 const baseFormat = displayFormat.replace('z', ''); const baseFormatted = formatDate(date, baseFormat, this.locale); // 从Date对象提取时区缩写 const tzAbbr = date.toLocaleTimeString('en-US', { timeZoneName: 'short' }).split(' ').pop(); return `${baseFormatted} ${tzAbbr}`; } return super.format(date, displayFormat); } }
- 模块配置替换适配器:
import { NgModule } from '@angular/core'; import { NgxMatDatetimePickerModule, NgxMatTimepickerModule, NgxMatNativeDateModule, NGX_MAT_DATETIME_FORMATS, NGX_MAT_NATIVE_DATETIME_ADAPTER_OPTIONS } from '@angular-material-components/datetime-picker'; import { CustomNativeDatetimeAdapter } from './custom-native-datetime-adapter'; export const CUSTOM_DATETIME_FORMATS = { parse: { dateInput: 'MMM D, YYYY, hh:mm A z', }, display: { dateInput: 'MMM D, YYYY, hh:mm A z', monthYearLabel: 'MMM YYYY', dateA11yLabel: 'LL', monthYearA11yLabel: 'MMMM YYYY', }, }; @NgModule({ imports: [NgxMatDatetimePickerModule, NgxMatTimepickerModule, NgxMatNativeDateModule], providers: [ { provide: NgxMatNativeDatetimeAdapter, useClass: CustomNativeDatetimeAdapter, deps: [NGX_MAT_NATIVE_DATETIME_ADAPTER_OPTIONS] }, { provide: NGX_MAT_DATETIME_FORMATS, useValue: CUSTOM_DATETIME_FORMATS } ] }) export class DatetimePickerConfigModule { }
注意事项
- 时区缩写存在歧义(比如CST可代表中国标准时间、美国中部标准时间等),若需更精准的时区标识,建议使用IANA时区名(如
Asia/Shanghai),但显示缩写只能按上述方式处理。 - 两种方案都需要在组件模块中导入配置好的
DatetimePickerConfigModule,并在模板中正常使用日期选择器组件即可。
内容的提问来源于stack exchange,提问作者SchwarzePete
相关产品推荐
相关产品推荐

