【问题标题】:Angular Material DatePicker: Date becomes one day before selected dateAngular Material DatePicker:日期变为所选日期前一天
【发布时间】:2017-06-25 08:08:07
【问题描述】:

我正在使用最新的 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.birthdayDate 类型。 但是当JSON.stringify(member.birthday) 时,它变为所选日期的前一天。例如:

从日期选择器中选择2017-4-1,字符串化结果为2017-03-31T13:00:00.000Z

This post 提出了同样的问题,但我不确定如何将moment.js 应用于代码。

【问题讨论】:

  • 您希望所选日期的格式是什么?例如:DD-MM-YYYY 表示 01-04-2017
  • 你的时区是-11:00吗?
  • 你能不能创建一个 plunkr 来重现
  • @RobG 我的时区是 GMT+1000 (AEST)

标签: angular angular-material2


【解决方案1】:

当我们在日期选择器中选择日期时,选择会以 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()}`);

您可以使用非常方便的时刻format() 功能来显示日期。

【讨论】:

  • 谢谢@Andriy!是的,实际上是格林威治时间,而不是 Material Datepicker 的错误。当我使用 moment 格式化 Datepicker 返回的日期时,它是正确的日期。
  • 好的,考虑到这一点,我的日期已正确存储在数据库中(使用格式 YYYY-MM-DD),但是当我从后端获取并将其显示在 mat- datepicker(使用 MAT_DATE_LOCALE = 'pt',使用格式 DD-MM-YYYY)它显示 1 天前。我该怎么办?
  • 尝试将日期存储为时间戳整数值,而不是字符串日期表示(可能已经受到您的时区的影响)。存储的日期值应为 UTC。显示时,日历将接受 UTC 时间并考虑您当前的时区进行转换/格式
【解决方案2】:

我通过创建一个自定义日期适配器(它继承了本地日期适配器)并重写 create-date 方法来删​​除时区偏移量来解决这个问题

@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

【讨论】:

    【解决方案3】:

    我们需要了解 Date 的工作原理。让我通过一些例子来说明我们如何创建一个日期对象。

    new Date('2020-08-22') // 22 aug 2020(your expect result)
    

    当您传递日期时,上述日期的输出取决于您的时区,它认为是 GMT。它会根据您的时区添加偏移量。假设你在 +0500 中,而不是打印出来

    2020 年 8 月 22 日星期六 05:00:00 GMT+0500

    它会将您的日期增加 5 小时。

    如果你在-0500,那么它会

    2020 年 8 月 21 日星期五 19:00:00 GMT-0500

    如果你想要 Date 总是给你你通过的日期而不添加偏移量。

    new Date(2020,07,22)
    

    2020 年 8 月 22 日星期六 00:00:00 GMT+0500

    它不会向日期对象添加小时(偏移量)。

    我只是通过第二种方法解决了这个问题,它对我有用。

    【讨论】:

      【解决方案4】:

      我正在使用 PHP 和 SQL,并以默认格式存储日期,例如 2021-04-12 00:00:00。 我想存储用户提供的实际值,所以我不费心转换时区。这无关紧要,在写这篇文章的那天,我只想要一个好的日期表示。

      这就是我存储给定日期的本地时间的原因:

      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)));
          })
      

      【讨论】:

        【解决方案5】:

        我希望这会有所帮助...只需获取 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');
        

        【讨论】:

          【解决方案6】:

          使用以下转换将解决您的问题。

            date =  new Date(this.moment(date).utcOffset('+0000').format('YYYY-MM-DD HH:MM'))
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2018-11-17
            • 2015-07-17
            • 1970-01-01
            • 2020-03-26
            • 1970-01-01
            • 2020-10-20
            • 1970-01-01
            • 2012-03-19
            相关资源
            最近更新 更多