Angular mat-datepicker显示日期错误:时区问题
问题描述
数据库中以UTC格式存储的日期为:
this.eventItem.date: "2023-06-21T00:00:00.000Z"
但表单输入框显示的值为2023-06-20,日期天数错误,推测是时区问题。当前声称所在时区为+3,执行console.log(new Date(this.eventItem.date));后,日志输出:
'Tue Jun 20 2023 21:00:00 GMT-0300 (hora estándar de Argentina)'
相关代码如下:
TypeScript 初始化代码
initializeForm(): void { this.detailsEventForm = this.fb.group({ isActive: [this.eventItem.isActive], date: '2023-06-21', shifts: [this.eventItem.shifts] }); }
HTML 表单代码
<mat-form-field floatLabel="auto" appearance="outline" color="primary"> <mat-label>Date</mat-label> <input matInput formControlName="date" [matDatepicker]="datePickerDate" readonly (click)="datePickerDate.open()"> <mat-datepicker-toggle [for]="datePickerDate" matSuffix></mat-datepicker-toggle> <mat-datepicker #datePickerDate></mat-datepicker> </mat-form-field>
解决方法
这个问题是Angular Material Datepicker默认按本地时区解析UTC日期导致的偏移,结合你的日志(实际运行环境为阿根廷GMT-3时区),提供两种可靠解决方式:
方式一:全局配置UTC日期适配器
让Datepicker全程以UTC时区处理日期,避免时区偏移:
- 自定义UTC适配类
import { NativeDateAdapter } from '@angular/material/core'; export class UtcDateAdapter extends NativeDateAdapter { override parse(value: any): Date | null { if (typeof value === 'string' && value.includes('Z')) { return new Date(value); } return super.parse(value); } override format(date: Date, displayFormat: Object): string { const utcDate = new Date(date.getTime() + date.getTimezoneOffset() * 60000); return super.format(utcDate, displayFormat); } }
- 在模块中注册适配器
import { NgModule } from '@angular/core'; import { MatDatepickerModule } from '@angular/material/datepicker'; import { MatNativeDateModule } from '@angular/material/core'; import { UtcDateAdapter } from './utc-date-adapter'; @NgModule({ imports: [MatDatepickerModule, MatNativeDateModule], providers: [ { provide: NativeDateAdapter, useClass: UtcDateAdapter } ] }) export class AppModule {}
方式二:手动转换UTC日期为本地正确格式
在初始化表单时,将UTC日期转换为运行环境时区的正确日期字符串:
initializeForm(): void { const utcDate = new Date(this.eventItem.date); // 针对阿根廷GMT-3时区,UTC转本地日期 const localDate = new Date(utcDate.getTime() - 3 * 60 * 60 * 1000); const formattedDate = localDate.toISOString().split('T')[0]; this.detailsEventForm = this.fb.group({ isActive: [this.eventItem.isActive], date: formattedDate, shifts: [this.eventItem.shifts] }); }
如果后续确认运行环境确实是+3时区,将转换逻辑改为utcDate.getTime() + 3 * 60 * 60 * 1000即可
内容的提问来源于stack exchange,提问作者sonEtLumiere
相关产品推荐
相关产品推荐

