Angular Material DatePicker: 日期变成所选日期前一天
Angular Material DatePicker: Date becomes one day before selected date
我正在使用最新的 Angular 4 和 Angular-Material2-2.0.0-beta7。这是我使用 MdDatePicker
:
的模板
<md-input-container fxFlex="33" class="birthday-container">
<input mdInput name="birthday" placeholder="Birthday" required [(ngModel)]="member.birthday" [mdDatepicker]="birthdayPicker">
<button mdSuffix [mdDatepickerToggle]="birthdayPicker"></button>
</md-input-container>
<md-datepicker #birthdayPicker></md-datepicker>
在 app.module 中,提供程序如下:
{provide: DateAdapter, useClass: NativeDateAdapter}
而member.birthday
是Date
类型。
但是当JSON.stringify(member.birthday)
时,就变成了选择日期的前一天。例如:
Select 2017-4-1
来自日期选择器,字符串化结果为 2017-03-31T13:00:00.000Z
.
This post 提出了同样的问题,但我不确定如何将 moment.js
应用于代码。
当我们在日期选择器中选择一个日期时,选择以 GMT(根据格林威治时区)时间存储和操作,但以格式化的表示形式显示给用户,同时考虑到用户的当前时区。因此存储和显示的日期不同(时区 +0 内的用户除外,如格林威治)。
当字符串化JS Date对象时,我们得到清晰的格林威治时区时间,我们可以在https://time.is/GMT看到它。您可能希望看到的是使用当前时区格式化的时间表示。查看我示例中的差异。
// get current time
let date = new Date();
console.log('NATIVE JS DATE TIME', date.toString());
console.log('STRINGIFIED TIME', JSON.stringify(date));
console.log('FORMATTED TIME', `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`);
你可以使用非常方便的moment的format()
功能来显示日期。
我通过创建一个自定义日期适配器(它继承了本机日期适配器)并覆盖创建日期方法来删除时区偏移来解决它
@Injectable({ providedIn: 'root' })
export class CustomDateAdapterService extends NativeDateAdapter {
public createDate(year: number, month: number, date: number): Date {
const localDate = super.createDate(year, month, date);
const offset = localDate.getTimezoneOffset() * 60000;
return new Date(localDate.getTime() - offset); // utcDate
}
}
你可以看看complete gist here
使用以下转换将解决您的问题。
date = new Date(this.moment(date).utcOffset('+0000').format('YYYY-MM-DD HH:MM'))
有一件事我们需要了解日期是如何工作的。让我通过一些示例来说明如何创建日期对象。
new Date('2020-08-22') // 22 aug 2020(your expect result)
以上日期的输出取决于您传递日期时的时区,它认为 GMT.it 根据您的时区添加偏移量。比方说你在 +0500 比它会打印
Sat Aug 22 2020 05:00:00 GMT+0500
你的约会时间增加了 5 小时。
如果你在 -0500,那么它将
Fri Aug 21 2020 19:00:00 GMT-0500
如果你想要 Date 总是给你你通过的日期而不添加偏移量。
new Date(2020,07,22)
Sat Aug 22 2020 00:00:00 GMT+0500
它不会向日期对象添加一个小时(偏移量)。
我只是通过第二种方法解决了这个问题,它对我有用。
我正在使用 PHP 和 SQL 并且我以默认格式存储日期,例如 2021-04-12 00:00:00
。
我想存储用户给出的实际值,所以我不用为转换时区而烦恼。这是无关紧要的,在写 post 的那一天,我只想要一个好的日期表示。
这就是我存储给定日期的本地时间的原因:
let phpDate = `${selectedDate.getFullYear()}-${selectedDate.getMonth()+1}-${selectedDate.getDate()} 00:00:00`;
// Notice that we have to add 1 to the zero-based JS month
解析存储日期:
this.date = new Date(
Number(d.substr(0, 4)),
Number(d.substr(5, 2)) -1, // we need to subtract 1 because JS mont is 0-based
Number(d.substr(8, 2)));
})
我希望这会有所帮助...只需获取 formgroup 的值并存储在 const 中,并在使用 datePipe 后重新分配 formcontrol 的值
import { DatePipe } from '@angular/common';
只需使用 component.ts 文件中的 Datepipe 并添加组件提供程序和构造函数
private datePipe: DatePipe,
providers: [DatePipe]
提交函数内部
const commonForm = {
...this.pollAdd.value,
};
commonForm.endDate=this.datePipe.transform(this.pollAdd.value.endDate, 'yyyy-MM-dd');
commonForm.startDate=this.datePipe.transform(this.pollAdd.value.startDate, 'yyyy-MM-dd');
我知道这很旧,但至少 Angular 12 和 mat-datepicker 仍然是个问题。我决定采取更直接的方法,而不是纠结于日期。
为了重申这个问题,我使用了来自 Angular Material 的日期选择器。当我在字段中输入 10/18/2018 然后将焦点移开时,没有任何反应。但是,如果用户在 2018-10-18 键入,它会更改为 10/17/2018。这让用户感到困惑。
由于这是唯一似乎有问题的输入格式,我使用该格式并进行了简单的文本转置。
在我的模板/.html 文件中:
<input matInput
id="cod-input"
formControlName="commercialOperationDate"
[min]="minDate"
[max]="maxDate"
[matDatepicker]="$any(codPicker)"
(change)="saveDateValue()"
(focusout)="formatDate()">
<mat-datepicker-toggle matSuffix
[for]="codPicker"></mat-datepicker-toggle>
<mat-datepicker #codPicker></mat-datepicker>
在我的组件/.ts 文件中:
public saveDateValue(): void {
this._codValue = (document.getElementById('cod-input') as HTMLInputElement).value;
}
public formatDate(): void {
const dateValue: string = this._codValue;
if (/^\d{4}-\d{2}-\d{2}$/.exec(dateValue)) {
length = dateValue.length;
const newDateStr =
`${dateValue.substring(length - 5, length - 3)}
/${dateValue.substring(length - 2)}
/${dateValue.substring(0, length - 6)}`;
this.accountLookupForm.get('commercialOperationDate').setValue(new Date(newDateStr))
}
}
总而言之,当用户更新输入字段时,我会保存输入字段的实际文本值。当用户改变焦点时,我根据有问题的正则表达式检查文本。然后我真的只是创建一个新字符串并根据更正后的格式设置日期。
我不确定这一切有多“专业”,但确实有效。即使我在日期选择器的输入字段中按回车键提交表单。
我正在使用最新的 Angular 4 和 Angular-Material2-2.0.0-beta7。这是我使用 MdDatePicker
:
<md-input-container fxFlex="33" class="birthday-container">
<input mdInput name="birthday" placeholder="Birthday" required [(ngModel)]="member.birthday" [mdDatepicker]="birthdayPicker">
<button mdSuffix [mdDatepickerToggle]="birthdayPicker"></button>
</md-input-container>
<md-datepicker #birthdayPicker></md-datepicker>
在 app.module 中,提供程序如下:
{provide: DateAdapter, useClass: NativeDateAdapter}
而member.birthday
是Date
类型。
但是当JSON.stringify(member.birthday)
时,就变成了选择日期的前一天。例如:
Select 2017-4-1
来自日期选择器,字符串化结果为 2017-03-31T13:00:00.000Z
.
This post 提出了同样的问题,但我不确定如何将 moment.js
应用于代码。
当我们在日期选择器中选择一个日期时,选择以 GMT(根据格林威治时区)时间存储和操作,但以格式化的表示形式显示给用户,同时考虑到用户的当前时区。因此存储和显示的日期不同(时区 +0 内的用户除外,如格林威治)。
当字符串化JS Date对象时,我们得到清晰的格林威治时区时间,我们可以在https://time.is/GMT看到它。您可能希望看到的是使用当前时区格式化的时间表示。查看我示例中的差异。
// get current time
let date = new Date();
console.log('NATIVE JS DATE TIME', date.toString());
console.log('STRINGIFIED TIME', JSON.stringify(date));
console.log('FORMATTED TIME', `${date.getHours()}:${date.getMinutes()}:${date.getSeconds()}`);
你可以使用非常方便的moment的format()
功能来显示日期。
我通过创建一个自定义日期适配器(它继承了本机日期适配器)并覆盖创建日期方法来删除时区偏移来解决它
@Injectable({ providedIn: 'root' })
export class CustomDateAdapterService extends NativeDateAdapter {
public createDate(year: number, month: number, date: number): Date {
const localDate = super.createDate(year, month, date);
const offset = localDate.getTimezoneOffset() * 60000;
return new Date(localDate.getTime() - offset); // utcDate
}
}
你可以看看complete gist here
使用以下转换将解决您的问题。
date = new Date(this.moment(date).utcOffset('+0000').format('YYYY-MM-DD HH:MM'))
有一件事我们需要了解日期是如何工作的。让我通过一些示例来说明如何创建日期对象。
new Date('2020-08-22') // 22 aug 2020(your expect result)
以上日期的输出取决于您传递日期时的时区,它认为 GMT.it 根据您的时区添加偏移量。比方说你在 +0500 比它会打印
Sat Aug 22 2020 05:00:00 GMT+0500
你的约会时间增加了 5 小时。
如果你在 -0500,那么它将
Fri Aug 21 2020 19:00:00 GMT-0500
如果你想要 Date 总是给你你通过的日期而不添加偏移量。
new Date(2020,07,22)
Sat Aug 22 2020 00:00:00 GMT+0500
它不会向日期对象添加一个小时(偏移量)。
我只是通过第二种方法解决了这个问题,它对我有用。
我正在使用 PHP 和 SQL 并且我以默认格式存储日期,例如 2021-04-12 00:00:00
。
我想存储用户给出的实际值,所以我不用为转换时区而烦恼。这是无关紧要的,在写 post 的那一天,我只想要一个好的日期表示。
这就是我存储给定日期的本地时间的原因:
let phpDate = `${selectedDate.getFullYear()}-${selectedDate.getMonth()+1}-${selectedDate.getDate()} 00:00:00`;
// Notice that we have to add 1 to the zero-based JS month
解析存储日期:
this.date = new Date(
Number(d.substr(0, 4)),
Number(d.substr(5, 2)) -1, // we need to subtract 1 because JS mont is 0-based
Number(d.substr(8, 2)));
})
我希望这会有所帮助...只需获取 formgroup 的值并存储在 const 中,并在使用 datePipe 后重新分配 formcontrol 的值
import { DatePipe } from '@angular/common';
只需使用 component.ts 文件中的 Datepipe 并添加组件提供程序和构造函数
private datePipe: DatePipe,
providers: [DatePipe]
提交函数内部
const commonForm = {
...this.pollAdd.value,
};
commonForm.endDate=this.datePipe.transform(this.pollAdd.value.endDate, 'yyyy-MM-dd');
commonForm.startDate=this.datePipe.transform(this.pollAdd.value.startDate, 'yyyy-MM-dd');
我知道这很旧,但至少 Angular 12 和 mat-datepicker 仍然是个问题。我决定采取更直接的方法,而不是纠结于日期。
为了重申这个问题,我使用了来自 Angular Material 的日期选择器。当我在字段中输入 10/18/2018 然后将焦点移开时,没有任何反应。但是,如果用户在 2018-10-18 键入,它会更改为 10/17/2018。这让用户感到困惑。
由于这是唯一似乎有问题的输入格式,我使用该格式并进行了简单的文本转置。
在我的模板/.html 文件中:
<input matInput
id="cod-input"
formControlName="commercialOperationDate"
[min]="minDate"
[max]="maxDate"
[matDatepicker]="$any(codPicker)"
(change)="saveDateValue()"
(focusout)="formatDate()">
<mat-datepicker-toggle matSuffix
[for]="codPicker"></mat-datepicker-toggle>
<mat-datepicker #codPicker></mat-datepicker>
在我的组件/.ts 文件中:
public saveDateValue(): void {
this._codValue = (document.getElementById('cod-input') as HTMLInputElement).value;
}
public formatDate(): void {
const dateValue: string = this._codValue;
if (/^\d{4}-\d{2}-\d{2}$/.exec(dateValue)) {
length = dateValue.length;
const newDateStr =
`${dateValue.substring(length - 5, length - 3)}
/${dateValue.substring(length - 2)}
/${dateValue.substring(0, length - 6)}`;
this.accountLookupForm.get('commercialOperationDate').setValue(new Date(newDateStr))
}
}
总而言之,当用户更新输入字段时,我会保存输入字段的实际文本值。当用户改变焦点时,我根据有问题的正则表达式检查文本。然后我真的只是创建一个新字符串并根据更正后的格式设置日期。
我不确定这一切有多“专业”,但确实有效。即使我在日期选择器的输入字段中按回车键提交表单。