首页 > 解决方案 > 日期是前一天

问题描述

我在我的日期选择器中选择日期May 01 1985并发dateOfBirth.value送到我的服务器,以便它可以存储在数据库中。

<mat-form-field>
  <label><input #dateOfBirth matInput (blur)="_update('personal', 'dateOfBirth', dateOfBirth.value)" (click)="picker.open()" [matDatepicker]="picker" placeholder="Choose a date" formControlName="dateOfBirth" autocomplete="off" [max]="maxDate" [min]="minDate"></label>
  <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
  <mat-datepicker touchUi #picker startView="multi-year"></mat-datepicker>
  <mat-error *ngIf="profileFormGroup.get('dateOfBirth').errors">Date is not valid</mat-error>
</mat-form-field>

每当我刷新页面时,所选日期应该仍然可见。

我的问题是,我选择了日期05/01/1985,但我的日期选择器显示了4/30/1985。为什么?

private static _formatDate(timestamp: number): string {
  console.log(timestamp); // Returns 483746400000
  const date = new Date(+timestamp);
  console.log(date.getDay()); // Returns 3 but it should be 1
  return date.toISOString().substring(0, 10);
}

ngOnInit() {
  this.profileService.getEntities().subscribe(data => {
  this.profileFormGroup.get('dateOfBirth').patchValue(ProfileComponent._formatDate(data.dateOfBirth));
  });
}

这是我在数据库中存储时间戳的方式:

private _update(tableName: string, columnName: string, theValue: any) {
  // Set the correct value of dateOfBirth
  console.log(theValue); // Returns 5/1/1985
  if (columnName === 'dateOfBirth') {
    const splitDate = theValue.split('/');
    const newDate = `${splitDate[2]}/${splitDate[0]}/${splitDate[1]}`;
    theValue = new Date(newDate).getTime();
    console.log(theValue); // Returns 483746400000
  }

  const json = {
      table: tableName,
      column: columnName,
      value: theValue
  };

  this.profileService.update(json).subscribe(result => {
    console.log(result);
  });
}

我还在Stackblitz 上检查了类似这样的其他示例。如果选择日期01/05/2020 ,输出将是2020-04-30T22 :00:00.000Z,这是错误的。

标签: angulardatepickertimestamp

解决方案


根据您所在的地区,五月属于夏令时。

设置 1985 年 5 月 1 日的日期应该就像1985-05-01T00:00.000+1:00您保留时区一样。

看起来正在发生的是您正在以 UTC 格式提取日期。这会将日期转换为 +0:00,从而将您带到前一天的1985-04-30T23:00.000+0.00.

如果您尝试 Stackblitz,问题就得到了证明 - 选择 3 月底之前和 10 月底之后的日期 - 这些日期可以正常工作,因为它们不是夏令时。

您的格式日期函数使用.toISOString(). 根据 Mozzila (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toISOString),这将始终返回 UTC 时间,并且您的日期会晚一小时,因此时值午夜,倒到前一天。

由于您只关心日期,并且日期选择器可能会以每种方式抵消最多 12 小时,我们可以检查这一点。

默认日期始终为午夜,因此在 UTC 之前的任何时间都可以,因为它将保持相同的日期。任何落后于 UTC 的时间都可以追溯到 12 小时,并一直持续到第二天。

在代码中,检查时区偏移会告诉我们是否落后。如果是这样,那么我们希望将小时数添加到 datetime 对象中,以便在使用时toISOString我们仍然可以选择日期。

所以函数应该如下:

const date = new Date(+timestamp);
const offset = date.getTimezoneOffset();
if (offset < 0) {
    date.setHours(12,0,0);
}
return date.toISOString().substring(0,10);

推荐阅读