简体   繁体   English

Angular Material 2(MatDatepickerModule)-在日期选择器中选择的日期关闭了1天

[英]Angular Material 2 (MatDatepickerModule) - The date selected in the date picker is off by 1 day

I am working on an Angular application (v4.4.3) with Angular Material Beta 11 version. 我正在使用Angular Material Beta 11版本处理Angular应用程序(v4.4.3)。 With beta 11, the datepicker is accepting date in ISOformat string. 在beta 11中,日期选择器正在接受ISOformat字符串中的日期。 However, in my app the date in the date picker module is off by 1 day , as shown in below image: 但是,在我的应用中,日期选择器模块中的日期关闭了1天 ,如下图所示:

在此处输入图片说明

The flow of date in my app is follows, the app receives a date in Unix Epoch time from Mysql database and I convert that Epoch time date into ISOString string format and return that ISO date to matDatePicker. 我的应用程序中的日期流如下所示,该应用程序从Mysql数据库接收Unix Epoch时间的日期,然后将该Epoch时间日期转换为ISOString字符串格式,并将该ISO日期返回给matDatePicker。

/**
 * This method takes the key, which is a epoch time in string format and convert into JS Date object.
 * @param key {string} - the epoch time
 * @return {string} - Date Object.
 */
private static dateHelper(key: string): any {
    const dateObj = new Date(+key * 1000);
    // Need to return ISOString format date as accepted by Material DatePicker component
    return dateObj.toISOString().substring(0, 10);

}

I also have Date Picker Module, to display the date in customized format: 我还有日期选择器模块,以自定义格式显示日期:

import {NgModule} from '@angular/core';
import {MdDatepickerModule, MdNativeDateModule, NativeDateAdapter, DateAdapter, MD_DATE_FORMATS} from '@angular/material';

// extend NativeDateAdapter's format method to specify the date format.
export class CustomDateAdapter extends NativeDateAdapter {
    format(date: Date, displayFormat: Object): string {
        if (displayFormat === 'input') {
            const day = date.getUTCDate();
            const month = date.getUTCMonth() + 1;
            const year = date.getFullYear();
            return `${year}-${month}-${day}`;
        } else {
            return date.toDateString();
        }
    }
}

const MY_DATE_FORMATS = {
    parse: {
        dateInput: {month: 'short', year: 'numeric', day: 'numeric'}
    },
    display: {
        dateInput: 'input',
        monthYearLabel: {year: 'numeric', month: 'short'},
        dateA11yLabel: {year: 'numeric', month: 'long', day: 'numeric'},
        monthYearA11yLabel: {year: 'numeric', month: 'long'},
    }
};

@NgModule({
    declarations: [],
    imports: [],
    exports: [MdDatepickerModule, MdNativeDateModule],
    providers: [
        {
            provide: DateAdapter, useClass: CustomDateAdapter
        },
        {
            provide: MD_DATE_FORMATS, useValue: MY_DATE_FORMATS
        }
    ]
})

export class DatePickerModule {

}

The DatePicker: DatePicker:

    <mat-form-field>
            <input matInput
                   [matDatepicker]="myDate"
                   placeholder="Start Date"                       
                   [(ngModel)]="date"
                   name="start_date" required>
            <mat-datepicker-toggle matSuffix [for]="myDate"></mat-datepicker-toggle>
            <mat-datepicker #myDate></mat-datepicker>
            <mat-error>This field is required!</mat-error>
        </mat-form-field>

I did Google about it and there were some posts with this issue but I was not able to follow them completely. 我曾在Google上进行过搜索,并且有一些有关此问题的帖子,但我无法完全关注它们。 Any input of this would be highly appreciated. 任何对此的投入将不胜感激。 Thanks! 谢谢!

It should work if you use date.getDate() and date.getMonth() , not date.getUTCDate() and date.getUTCMonth() , in the format method in your custom date adapter. 如果您在自定义日期适配器的format方法中使用date.getDate()date.getMonth() 而不是 date.getUTCDate()date.getUTCMonth() ,则它应该可以工作。

Try and let us know: 尝试让我们知道:

export class CustomDateAdapter extends NativeDateAdapter {
    format(date: Date, displayFormat: Object): string {
           if (displayFormat == "input") {
               let day = date.getDate();
               let month = date.getMonth() + 1;
               let year = date.getFullYear();
               return `${year}-${month}-${day}`
           } else {
               return date.toDateString();
           }
       }
}

Got it resolved. 解决了。 Thanks Everyone for their inputs. 感谢大家的投入。

So after having some discussion here and going through the Angular Material 2 Github issues and posts, I got some ideas and ways to assign the Date to DatePicker component. 因此,在这里进行了讨论并讨论了Angular Material 2 Github的问题和帖子之后,我得到了一些将Date分配给DatePicker组件的想法和方法。 With Material beta 11, the DatePicker component can take date as Date or ISOString format. 在Material beta 11中,DatePicker组件可以将日期作为DateISOString格式。 I was having the issue when I was using the ISOString format. 我在使用ISOString格式时遇到问题。 I just updated it to normal Date format as shown below. 我刚刚将其更新为正常的Date格式,如下所示。

The updated code snippets from my Question: 我的问题的更新代码段:

 /**
 * This method takes the key, which is a epoch time in string format and 
 * convert into JS Date object.
 * @param key {string} - the epoch time
 * @return {string} - Date Object.
 */
private static dateHelper(key: string): any {
    const dateObj = new Date(+key * 1000);
    // Need to return Date object/ISOString format date as accepted by Material DatePicker component
    return new Date(dateObj.getFullYear(), dateObj.getUTCMonth(), dateObj.getUTCDate());;

}

This was the only change I did to match the date in mdInput and the calendar. 这是我所做的唯一更改,以匹配mdInput和日历中的日期。 I am not still sure the reason for the issue when I was using ISOString format. 我仍不确定使用ISOString格式时出现此问题的原因。 Also, I realized I do not need to use any CustomDateAdapter as it's mainly for appearance purpose. 另外,我意识到我不需要使用任何CustomDateAdapter因为它主要用于外观目的。

With out debugging in a console, a date somewhere is being represented with a timezone most likely. 如果没有在控制台中进行调试,则最有可能用某个时区来表示某个日期。 And the difference between the represented time zone, and UTC is 1 day. 所表示的时区与UTC之间的时差为1天。

It may be the date.toDataString(). 它可能是date.toDataString()。

See this . 看到这个

I am not quite sure of this, but my suspicion would be on the epoch time to Date conversion and the Time Zone influence on it. 我对此不太确定,但我怀疑是从DateDate转换以及时区对其的影响。 Try this approach to convert the DB time. 尝试使用这种方法来转换数据库时间。

Most likely in this line, 最有可能在这一行中

const dateObj = new Date(+key * 1000);

the Date constructor might initialize the date based on your local (system) TZ and that might offset things from the UTC time. Date构造函数可能会根据您本地(系统)的TZ来初始化日期,这可能会使UTC时间偏离日期。

EDIT 编辑

Okay, digged a little deeper. 好吧,深入一点。 I think I have ball parked the reason for this issue. 我想我已经把这个问题停下来了。 You may have to customize the parse() method as well in your CustomDateAdapter as it actually converts the given date (UTC) to that of a local time (zone) date as per this inbuilt parse() method. 您可能还必须在CustomDateAdapter自定义parse()方法,因为它实际上会按照内置parse()方法将给定date (UTC)转换为本地时间(区域)日期。

Try adding something to the effect of this in your CustomDateAdapter, 尝试在CustomDateAdapter中添加一些效果,

parse(value: any): Date | null {
 if (typeof value == 'number') {
  return new Date(value); // not likely to enter here as your date is in 'string' format
 }
 return value ? new Date(Date.parse(value + ' GMT')) : null; //forces Time Zone to GMT/UTC and converts it
}

See if it fixes your issue. 查看是否可以解决您的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM