Angular material 使用Material dayjs日期适配器处理分隔符

Angular material 使用Material dayjs日期适配器处理分隔符,angular-material,dayjs,Angular Material,Dayjs,在我的角度应用程序中,我需要从切换到。 因为我使用的是dayjs日期适配器,所以我必须用dayjs日期适配器替换MomentDate adapter,所以我编写了自己的日期适配器,但我无法理解momentjs如何在没有任何分隔符的情况下解析像12122020这样的日期(您可以看到它正在运行) 我试图通过设置这个MatDateFormats,并使用一个dateinput数组来实现它。 但我不知道这是否是最好的解决方案,因为我在当前日期适配器中看不到它 MatDateFormats = { pars

在我的角度应用程序中,我需要从切换到。 因为我使用的是dayjs日期适配器,所以我必须用dayjs日期适配器替换
MomentDate adapter
,所以我编写了自己的日期适配器,但我无法理解momentjs如何在没有任何分隔符的情况下解析像
12122020
这样的日期(您可以看到它正在运行)

我试图通过设置这个
MatDateFormats
,并使用一个dateinput数组来实现它。 但我不知道这是否是最好的解决方案,因为我在当前日期适配器中看不到它

MatDateFormats = {
parse: {
    dateInput: ['D/M/YYYY', 'DMYYYY'],
},
display: {
    dateInput: 'DD/MM/YYYY',
    monthYearLabel: 'MMMM YYYY',
    dateA11yLabel: 'DD/MM/YYYY',
    monthYearA11yLabel: 'MMMM YYYY',
}
}

这是我的
dayjs日期适配器

export interface DayJsDateAdapterOptions {
/**
 * Turns the use of utc dates on or off.
 * Changing this will change how Angular Material components like DatePicker output dates.
 * {@default false}
 */
useUtc?: boolean;
}

/** InjectionToken for Dayjs date adapter to configure options. */
export const MAT_DAYJS_DATE_ADAPTER_OPTIONS = new InjectionToken<DayJsDateAdapterOptions>(
'MAT_DAYJS_DATE_ADAPTER_OPTIONS', {
    providedIn: 'root',
    factory: MAT_DAYJS_DATE_ADAPTER_OPTIONS_FACTORY
});

export function MAT_DAYJS_DATE_ADAPTER_OPTIONS_FACTORY(): DayJsDateAdapterOptions {
 return {
    useUtc: false
 };
}

/** Creates an array and fills it with values. */
function range<T>(length: number, valueFunction: (index: number) => T): T[] {
 const valuesArray = Array(length);
 for (let i = 0; i < length; i++) {
    valuesArray[i] = valueFunction(i);
 }
 return valuesArray;
}

/** Adapts Dayjs Dates for use with Angular Material. */
export class DayjsDateAdapter extends DateAdapter<Dayjs> {
 private localeData: {
    firstDayOfWeek: number,
    longMonths: string[],
    shortMonths: string[],
    dates: string[],
    longDaysOfWeek: string[],
    shortDaysOfWeek: string[],
    narrowDaysOfWeek: string[]
 };

constructor(@Optional() @Inject(MAT_DATE_LOCALE) public dateLocale: string,
            @Optional() @Inject(MAT_DAYJS_DATE_ADAPTER_OPTIONS) private options?: 
   DayJsDateAdapterOptions) {
    super();

    this.initializeParser(dateLocale);
  }

private get shouldUseUtc(): boolean {
    const {useUtc}: DayJsDateAdapterOptions = this.options || {};
    return !!useUtc;
}

// TODO: Implement
setLocale(locale: string) {
    super.setLocale(locale);

    const dayJsLocaleData = this.dayJs().localeData();
    this.localeData = {
        firstDayOfWeek: dayJsLocaleData.firstDayOfWeek(),
        longMonths: dayJsLocaleData.months(),
        shortMonths: dayJsLocaleData.monthsShort(),
        dates: range(31, (i) => this.createDate(2017, 0, i + 1).format('D')),
        longDaysOfWeek: range(7, (i) => this.dayJs().set('day', i).format('dddd')),
        shortDaysOfWeek: dayJsLocaleData.weekdaysShort(),
        narrowDaysOfWeek: dayJsLocaleData.weekdaysMin(),
    };
}

getYear(date: Dayjs): number {
    return this.dayJs(date).year();
}

getMonth(date: Dayjs): number {
    return this.dayJs(date).month();
}

getDate(date: Dayjs): number {
    return this.dayJs(date).date();
}

getDayOfWeek(date: Dayjs): number {
    return this.dayJs(date).day();
}

getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
    return style === 'long' ? this.localeData.longMonths : this.localeData.shortMonths;
}

getDateNames(): string[] {
    return this.localeData.dates;
}

getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] {
    if (style === 'long') {
        return this.localeData.longDaysOfWeek;
    }
    if (style === 'short') {
        return this.localeData.shortDaysOfWeek;
    }
    return this.localeData.narrowDaysOfWeek;
}

getYearName(date: Dayjs): string {
    return this.dayJs(date).format('YYYY');
}

getFirstDayOfWeek(): number {
    return this.localeData.firstDayOfWeek;
}

getNumDaysInMonth(date: Dayjs): number {
    return this.dayJs(date).daysInMonth();
}

clone(date: Dayjs): Dayjs {
    return date.clone();
}

createDate(year: number, month: number, date: number): Dayjs {
    const returnDayjs = this.dayJs()
        .set('year', year)
        .set('month', month)
        .set('date', date);
    return returnDayjs;
}

today(): Dayjs {
    return this.dayJs();
}

parse(value: any, parseFormat: string): Dayjs | null {
    if (value && typeof value === 'string') {
        return this.dayJs(value, parseFormat, this.locale);
    }
    return value ? this.dayJs(value).locale(this.locale) : null;
}

format(date: Dayjs, displayFormat: string): string {
    if (!this.isValid(date)) {
        throw Error('DayjsDateAdapter: Cannot format invalid date.');
    }
    return date.locale(this.locale).format(displayFormat);
}

addCalendarYears(date: Dayjs, years: number): Dayjs {
    return date.add(years, 'year');
}

addCalendarMonths(date: Dayjs, months: number): Dayjs {
    return date.add(months, 'month');
}

addCalendarDays(date: Dayjs, days: number): Dayjs {
    return date.add(days, 'day');
}

toIso8601(date: Dayjs): string {
    return date.toISOString();
}


deserialize(value: any): Dayjs | null {
    let date;
    if (value instanceof Date) {
        date = this.dayJs(value);
    } else if (this.isDateInstance(value)) {
        // NOTE: assumes that cloning also sets the correct locale.
        return this.clone(value);
    }
    if (typeof value === 'string') {
        if (!value) {
            return null;
        }
        date = this.dayJs(value).toISOString();
    }
    if (date && this.isValid(date)) {
        return this.dayJs(date);
    }
    return super.deserialize(value);
}

isDateInstance(obj: any): boolean {
    return dayjs.isDayjs(obj);
}

isValid(date: Dayjs): boolean {
    return this.dayJs(date).isValid();
}

invalid(): Dayjs {
    return this.dayJs(null);
}

private dayJs(input?: any, format?: string, locale?: string): Dayjs {
    if (!this.shouldUseUtc) {
        return dayjs(input, format, locale, false);
    }
    return dayjs(input, {format, locale, utc: this.shouldUseUtc}, locale, false).utc();
}

private initializeParser(dateLocale: string) {
    if (this.shouldUseUtc) {
        dayjs.extend(utc);
    }

    dayjs.extend(LocalizedFormat);
    dayjs.extend(customParseFormat);
    dayjs.extend(localeData);

 }
}
导出接口DayJsDateAdapterOptions{
/**
*打开或关闭utc日期的使用。
*更改此选项将更改角度材质组件(如DatePicker)输出日期的方式。
*{@default false}
*/
useUtc?:布尔值;
}
/**Dayjs日期适配器的InjectionToken用于配置选项*/
export const MAT_DAYJS_DATE_ADAPTER_OPTIONS=新注入令牌(
“MAT_DAYJS_DATE_ADAPTER_OPTIONS”{
providedIn:'根',
工厂:MAT_DAYJS_DATE_ADAPTER_OPTIONS_工厂
});
导出函数MAT_DAYJS_DATE_ADAPTER_OPTIONS_FACTORY():dayjsdateadapter选项{
返回{
useUtc:false
};
}
/**创建一个数组并用值填充它*/
函数范围(长度:number,值函数:(索引:number)=>T):T[]{
常量值数组=数组(长度);
for(设i=0;ithis.createDate(2017,0,i+1).format('D'),
longDaysOfWeek:range(7,(i)=>this.dayJs().set('day',i).format('dddddd'),
shortDaysOfWeek:dayJsLocaleData.weekdaysShort(),
NerrowDaysOfWeek:dayJsLocaleData.weekdaysMin(),
};
}
getYear(日期:Dayjs):编号{
返回this.dayJs(date.year();
}
getMonth(日期:Dayjs):编号{
返回this.dayJs(date.month();
}
getDate(日期:Dayjs):编号{
返回this.dayJs(date.date();
}
getDayOfWeek(日期:Dayjs):编号{
返回this.dayJs(date.day();
}
getMonthNames(样式:“长”|“短”|“窄”):字符串[]{
返回样式=='long'?this.localeData.longMonths:this.localeData.shortMonths;
}
getDateNames():字符串[]{
返回this.localeData.dates;
}
getDayOfWeekNames(样式:“长”|“短”|“窄”):字符串[]{
如果(样式=='long'){
返回this.localeData.longDaysOfWeek;
}
如果(样式=='short'){
返回this.localeData.shortDaysOfWeek;
}
返回this.localeData.窄带daysofweek;
}
GetDreamName(日期:Dayjs):字符串{
返回此.dayJs(date.format('YYYY');
}
getFirstDayOfWeek():编号{
返回this.localeData.firstDayOfWeek;
}
getNumDaysInMonth(日期:Dayjs):编号{
返回此.dayJs(date.daysInMonth();
}
克隆(日期:Dayjs):Dayjs{
返回日期。克隆();
}
createDate(年:编号,月:编号,日期:编号):Dayjs{
const returnDayjs=this.dayJs()
.set('年',年)
.set('月',月)
.set('日期',日期);
returnDayjs;
}
今天():Dayjs{
返回this.dayJs();
}
解析(值:any,解析格式:string):Dayjs | null{
if(value&&typeof value==='string'){
返回this.dayJs(值,parseFormat,this.locale);
}
返回值?this.dayJs(value.locale)(this.locale):null;
}
格式(日期:Dayjs,显示格式:string):string{
如果(!this.isValid(日期)){
抛出错误('DayjsDateAdapter:无法设置无效日期的格式');
}
返回date.locale(this.locale).format(displayFormat);
}
addCalendarYears(日期:Dayjs,年份:number):Dayjs{
返回日期。添加(年,'年');
}
addCalendarMonths(日期:Dayjs,月份:编号):Dayjs{
返回日期。添加(月,'月');
}
addCalendarDays(日期:Dayjs,天数:number):Dayjs{
返回日期。添加(天,'天');
}
toIso8601(日期:Dayjs):字符串{
返回日期。toISOString();
}
反序列化(值:any):Dayjs | null{
让我们约会;
if(值instanceof Date){
日期=此.dayJs(值);
}else if(this.isDateInstance(值)){
//注意:假定克隆还设置了正确的区域设置。
返回此.clone(值);
}
如果(值的类型=='string'){
如果(!值){
返回null;
}
日期=this.dayJs(value.toISOString();
}
if(date&&this.isValid(date)){
返回此.dayJs(日期);
}
返回super.deserialize(值);
}
isDateInstance(对象:任意):布尔值{
返回日js.isDayjs(obj);
}
isValid(日期:Dayjs):布尔值{
返回this.dayJs(date.isValid();
}
无效():Dayjs{
返回this.dayJs(null);
}
private dayJs(输入?:任意,格式?:字符串,区域设置?:字符串):dayJs{
如果(!this.shouldUseUtc){
返回dayjs(输入、格式、区域设置、false);
}
返回dayjs(输入,{format,locale,utc:this.shouldUseUtc},locale,false).utc();
}
私有初始值分析器(dateLocale:string){
if(this.shouldUseUtc){
延长日(utc);
}
dayjs.extend
parse(value: any, parseFormats: string[]): Dayjs | null {
    if (value && typeof value === 'string') {
        parseFormats.forEach(parseFormat => {
            const parsed = this.dayJs(value, parseFormat, this.locale);
            if (parsed.isValid()) {
                return parsed;
            }
        }
        // return an invalid object if it could not be parsed with the supplied formats
        return this.dayJs(null);
}
    return value ? this.dayJs(value).locale(this.locale) : null;
}
private dayJs(input?: any, format?: string, locale?: string): Dayjs {
    return dayjs(input, format, locale);
}
parse(value: any, parseFormat: string): Dayjs | null {
    if (value && typeof value === 'string') {
        const longDateFormat = dayjs().localeData().longDateFormat(parseFormat); // MM/DD/YYY or DD-MM-YYYY, etc.
        // return this.dayJs(value, longDateFormat);
        let parsed = this.dayJs(value, longDateFormat, this.locale);
        if (parsed.isValid()) {
            // string value is exactly like long date format
            return parsed;
        }
        const alphaNumericRegex = /[\W_]+/;
        if (!alphaNumericRegex.test(value)) {
            // if string contains no non-word characters and no _
            // user might have typed 24012020 or 01242020
            // strip long date format of non-word characters and take only the length of the value so we get DDMMYYYY or DDMM etc
            const format = longDateFormat.replace(/[\W_]+/g, '').substr(0, value.length);
            parsed = this.dayJs(value, format, this.locale);
            if (parsed.isValid()) {
                return parsed;
            }
        }
        const userDelimiter = alphaNumericRegex.exec(value) ? alphaNumericRegex.exec(value)![0] : '';
        const localeDelimiter = alphaNumericRegex.exec(longDateFormat) ? alphaNumericRegex.exec(longDateFormat)![0] : '';
        const parts = value.split(userDelimiter);
        const formatParts = longDateFormat.split(localeDelimiter);
        if (parts.length <= formatParts.length && parts.length < 4) {
            // right now this only works for days, months, and years, if time should be supported this should be altered
            let newFormat = '';
            parts.forEach((part, index) => {
                // get the format in the length of the part, so if a the date is supplied 1-1-19 this should result in D-M-YY
                // note, this will not work if really weird input is supplied, but that's okay
                newFormat += formatParts[index].substr(0, part.length);
                if (index < parts.length - 1) {
                    newFormat += userDelimiter;
                }
            });
            parsed = this.dayJs(value, newFormat);
            if (parsed.isValid()) {
                return parsed;
            }
        }

        // not able to parse anything sensible, return something invalid so input can be corrected
        return this.dayJs(null);
    }

    return value ? this.dayJs(value).locale(this.locale) : null;
}