Angular 2/4/5:如何将UTC格式日期绑定到mat-datepicker
嘿,刚接触Angular和Angular Material遇到这个问题很正常,我来帮你搞定这个日期绑定的事儿~
首先得明确:mat-datepicker 默认只认标准的ISO日期字符串(比如2018-04-11T02:12:04.455Z)或者JavaScript的Date对象,你后端返回的2018-04-11T02:12:04.455Z[UTC]因为多了[UTC]后缀,它识别不了,所以得先做两步处理:解析后端日期为Date对象,以及提交时转回后端需要的格式,另外你的HTML里还有个变量冲突的小问题,也得修正。
1. 处理日期格式的解析与格式化
在你的组件里写两个工具函数,分别用来把后端的带时区后缀的日期转成Date对象,以及把Date对象转回后端需要的格式:
// 解析后端的zonedDate格式为Date对象 parseZonedDate(dateStr: string): Date | null { // 去掉末尾的[UTC]部分,得到标准ISO字符串 const isoDateStr = dateStr.replace(/\[[^\]]+\]$/, ''); const date = new Date(isoDateStr); // 校验日期是否有效 return isNaN(date.getTime()) ? null : date; } // 把Date对象格式化成后端需要的zonedDate格式 formatToZonedDate(date: Date): string { const isoStr = date.toISOString(); return `${isoStr}[UTC]`; }
然后在组件初始化或者获取后端数据的时候,用parseZonedDate处理日期:
// 假设从后端拿到的日期是backendDateStr const backendDateStr = "2018-04-11T02:12:04.455Z[UTC]"; this.myDate = this.parseZonedDate(backendDateStr);
当你需要提交表单给后端时,再用formatToZonedDate转换回去:
const submitDate = this.formatToZonedDate(this.myDate); // 把submitDate传给后端接口
2. 修正HTML里的变量冲突问题
你的HTML代码里,[(ngModel)]="myDate"、#myDate="ngModel"和[matDatepicker]="myDate"用了同一个变量名myDate,这会导致模板变量冲突,mat-datepicker根本找不到正确的引用。修改一下变量名,比如把datepicker的引用改成#picker:
<mat-form-field class="fx-cell-1" floatLabel="never"> <input matInput name="myDate" [matDatepicker]="picker" placeholder="Date of Expense" [(ngModel)]="myDate" #myDateInput="ngModel" [max]="maxDate" required> <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle> <mat-datepicker #picker></mat-datepicker> </mat-form-field>
这样修改后,mat-datepicker就能正确绑定到输入框,同时ngModel的引用也不会冲突了。
额外提示(如果用响应式表单)
要是你用的是Reactive Forms,思路也是一样的:在设置表单控件值的时候先解析成Date对象,提交时再格式化:
// 设置表单值 this.myForm.get('myDate')?.setValue(this.parseZonedDate(backendDateStr)); // 提交时转换 const submitDate = this.formatToZonedDate(this.myForm.get('myDate')?.value);
这样应该就能完美解决你的日期绑定问题啦~
内容的提问来源于stack exchange,提问作者PiyaModi

