Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
2.9k views
in Technique[技术] by (71.8m points)

Handle separator with Material dayjs date adapter

In my Angular application I need to swap from momentjs to dayjs. Because I am using material I have to replace moment-date-adapter with a dayjs-date-adapter, so I write my own date adapter but I can't understand how momentjs can parse a date like 12122020 without any separator (you can see it in action here).

I try to achieve it by setting this MatDateFormats, with an array of dateinput. But I don't know if it is the best solution because I don't see it in moment-date-adapter

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

}

This is my dayjs-date-adapter

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

 }
}

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
等待大神答复

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...