All files / src/lib/forms/adapters date-picker-moment-adapter.ts

100% Statements 75/75
100% Branches 35/35
100% Functions 19/19
100% Lines 70/70

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 1421x   1x                   1x             145x 145x 145x   145x 145x   145x 144x   144x 56x   88x     1x       1x 5x   5x     1x 5x   5x     1x 12x   10x 10x   10x     1x 5x   5x     1x 5x     25x 15x     1x 10x 5x 5x 3x   2x       1x 5x     1x 5x     1x 5x 5x   5x     1x 5x     1x 5x     1x 5x     1x 25x 5x 5x 20x 5x 5x     25x     1x 16x     1x 50x 45x 45x     5x   1x   1x 1x      
import {Inject, Injectable, LOCALE_ID, Optional} from '@angular/core';
 
import {MOMENT, TIMEZONE_OVERRIDE} from '../../common/interfaces/Tokens';
import {DayWithMetadata} from '../interfaces/DayWithMetadata';
import {DateRangeValidationParams} from '../interfaces/DateRangeValidationParams';
import {DateAdapter} from '../services/date-picker.service';
 
/* Note: Typings of 'any' in this file refer to Moment.
         The Moment type does not come without the full weight of Moment.js, so it was intentionally left out. */
 
@Injectable()
// Adapter for Date-Picker to accept String, Native Date or Moment objects
export class MomentDateAdapter implements DateAdapter<any> {
 
    private moment: any;
    private timezone: string;
    private formatterLanguage: string;
 
    constructor(
        @Inject(MOMENT) private _moment: any,
        @Optional() @Inject(LOCALE_ID) private _locale?: string,
        @Optional() @Inject(TIMEZONE_OVERRIDE) private _timezone?: string) {
 
        this.moment = _moment;
        this.timezone = _timezone;
 
        if (this.moment) {
            this.moment.locale(this._locale);
 
            if (this.timezone) {
                this.moment.tz.setDefault(this.timezone);
            } else {
                console.warn('Timezone is not set, is defaulting to system timezone. TIMEZONE_OVERRIDE may be set at the Module level.');
            }
        } else {
            console.error('Package "moment" has not been installed. Please either install "moment" or use the NativeDateAdapter.');
        }
    }
 
    public dayOfFirst(year: number, month: number): number {
        const adjusted = this.handleMonthAdjustment(year, month);
 
        return this.moment([adjusted.year, adjusted.month, 1]).day();
    }
 
    public daysInMonth(year: number, month: number): number {
        const adjusted = this.handleMonthAdjustment(year, month);
 
        return this.moment([adjusted.year, adjusted.month]).daysInMonth();
    }
 
    public isDisabled(evalDate: Date, dateRangeParams: DateRangeValidationParams): boolean {
        if (!dateRangeParams || (!dateRangeParams.minDate && !dateRangeParams.maxDate)) { return false; }
 
        const dayIsBeforeMinDate = this.moment(evalDate).isBefore(this.moment(dateRangeParams.minDate), 'day');
        const dayIsAfterMaxDate = this.moment(evalDate).isAfter(this.moment(dateRangeParams.maxDate), 'day');
 
        return dayIsBeforeMinDate || dayIsAfterMaxDate;
    }
 
    public getMonthInfo(year: number, month: number): Date {
        const adjusted = this.handleMonthAdjustment(year, month);
 
        return new Date(this.moment([adjusted.year, adjusted.month, 15]));
    }
 
    public month(date: Date): number {
        return this.moment(date).month();
    }
 
    public newDateFromArray(year?: number, month: number = 0, day: number = 1): any {
        return new Date(this.moment([year, month, day]));
    }
 
    public newDateFromValue(value?: any): any {
        if (!value) {
            return new Date();
        } else if (value instanceof Date) {
            return new Date(this.moment(value));
        } else {
            return new Date(value);
        }
    }
 
    public prepHeaderDate(date: Date): string {
        return this.moment(date).locale(this.formatterLanguage || this._locale).format('ddd, MMM D');
    }
 
    public prepHeaderYear(date: Date): string {
        return this.moment(date).locale(this.formatterLanguage || this._locale).format('YYYY');
    }
 
    public sameDay(_calendarDay: DayWithMetadata, _comparator: Date): boolean {
        const calendarDay = this.moment([_calendarDay.year, _calendarDay.month, _calendarDay.day]);
        const comparator = this.moment(_comparator);
 
        return calendarDay.isSame(comparator, 'day');
    }
 
    public year(date: Date): number {
        return this.moment(date).year();
    }
 
    public weekdays(): string[] {
        return this.moment.weekdays();
    }
 
    public months(): string[] {
        return this.moment.monthsShort();
    }
 
    private handleMonthAdjustment(year: number, month: number): {year: number, month: number} {
        if (month > 11) {
            month = month - 12;
            year++;
        } else if (month < 0) {
            month = month + 12;
            year--;
        }
 
        return {year, month};
    }
 
    public prepDateStringOutput(input: any): string {
        return (input) ? this.moment(this.processDateInput(input)).format('l') : '';
    }
 
    public processDateInput(input: any): Date {
        if (input && this.moment(input, 'L', this._locale).isValid()) {
            const timezone = this.timezone || this.moment.tz.guess();
            return this.moment(input, 'L', this._locale).tz(timezone).startOf('day').toDate();
        }
 
        return new Date('false');
    }
}
 
export function getMomentDateAdapter(MOMENT_: any, locale?: string, timezone?: string): MomentDateAdapter {
    return new MomentDateAdapter(MOMENT_, locale, timezone);
}