Skip to content

Commit

Permalink
feat(material-luxon-adapter): add option to set default calendar (#27453
Browse files Browse the repository at this point in the history
)

* feat(material-luxon-adapter): add option to set default calendar

Add defaultOutputCalendar option to be able to change default calndar through MAT_LUXON_DATE_ADAPTER_OPTIONS

* feat(material-luxon-adapter): update options to add default calendar

Update options of luxon-date-adapter to add defaultOutputCalendar to be able to change default calndar through MAT_LUXON_DATE_ADAPTER_OPTIONS
  • Loading branch information
adotnusiyan authored Jul 18, 2023
1 parent d098bd2 commit 439d6fc
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 11 deletions.
37 changes: 36 additions & 1 deletion src/material-luxon-adapter/adapter/luxon-date-adapter.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import {LOCALE_ID} from '@angular/core';
import {TestBed, waitForAsync} from '@angular/core/testing';
import {DateAdapter, MAT_DATE_LOCALE} from '@angular/material/core';
import {DateTime, FixedOffsetZone, Settings} from 'luxon';
import {CalendarSystem, DateTime, FixedOffsetZone, Settings} from 'luxon';
import {LuxonDateModule} from './index';
import {MAT_LUXON_DATE_ADAPTER_OPTIONS} from './luxon-date-adapter';

Expand Down Expand Up @@ -632,6 +632,41 @@ describe('LuxonDateAdapter with MAT_LUXON_DATE_ADAPTER_OPTIONS override', () =>
});
});

describe('LuxonDateAdapter with MAT_LUXON_DATE_ADAPTER_OPTIONS override for defaultOutputCalendar option', () => {
let adapter: DateAdapter<DateTime>;

const calendarExample: CalendarSystem = 'islamic';

beforeEach(waitForAsync(() => {
TestBed.configureTestingModule({
imports: [LuxonDateModule],
providers: [
{
provide: MAT_LUXON_DATE_ADAPTER_OPTIONS,
useValue: {defaultOutputCalendar: calendarExample},
},
],
}).compileComponents();

adapter = TestBed.inject(DateAdapter);
}));

describe(`use ${calendarExample} calendar`, () => {
it(`should create Luxon date in ${calendarExample} calendar`, () => {
// Use 0 since createDate takes 0-indexed months.
expect(adapter.createDate(2017, 0, 2).toLocaleString()).toBe(
DateTime.local(2017, JAN, 2, {outputCalendar: calendarExample}).toLocaleString(),
);
});

it(`should create today in ${calendarExample} calendar`, () => {
expect(adapter.today().toLocaleString()).toBe(
DateTime.local({outputCalendar: calendarExample}).toLocaleString(),
);
});
});
});

function assertValidDate(adapter: DateAdapter<DateTime>, d: DateTime | null, valid: boolean) {
expect(adapter.isDateInstance(d))
.not.withContext(`Expected ${d} to be a date instance`)
Expand Down
39 changes: 29 additions & 10 deletions src/material-luxon-adapter/adapter/luxon-date-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
DateTime as LuxonDateTime,
Info as LuxonInfo,
DateTimeOptions as LuxonDateTimeOptions,
CalendarSystem as LuxonCalendarSystem,
} from 'luxon';

/** Configurable options for the `LuxonDateAdapter`. */
Expand All @@ -27,6 +28,12 @@ export interface MatLuxonDateAdapterOptions {
* Changing this will change how Angular Material components like DatePicker shows start of week.
*/
firstDayOfWeek: number;

/**
* Sets the output Calendar.
* Changing this will change how Angular Material components like DatePicker output dates.
*/
defaultOutputCalendar: LuxonCalendarSystem;
}

/** InjectionToken for LuxonDateAdapter to configure options. */
Expand All @@ -43,6 +50,7 @@ export function MAT_LUXON_DATE_ADAPTER_OPTIONS_FACTORY(): MatLuxonDateAdapterOpt
return {
useUtc: false,
firstDayOfWeek: 0,
defaultOutputCalendar: 'gregory',
};
}

Expand All @@ -60,6 +68,7 @@ function range<T>(length: number, valueFunction: (index: number) => T): T[] {
export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
private _useUTC: boolean;
private _firstDayOfWeek: number;
private _defaultOutputCalendar: LuxonCalendarSystem;

constructor(
@Optional() @Inject(MAT_DATE_LOCALE) dateLocale: string,
Expand All @@ -70,6 +79,7 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
super();
this._useUTC = !!options?.useUtc;
this._firstDayOfWeek = options?.firstDayOfWeek || 0;
this._defaultOutputCalendar = options?.defaultOutputCalendar || 'gregory';
this.setLocale(dateLocale || LuxonDateTime.local().locale);
}

Expand All @@ -91,7 +101,11 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
}

getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
return LuxonInfo.months(style, {locale: this.locale});
// Adding outputCalendar option, because LuxonInfo doesn't get effected by LuxonSettings
return LuxonInfo.months(style, {
locale: this.locale,
outputCalendar: this._defaultOutputCalendar,
});
}

getDateNames(): string[] {
Expand All @@ -113,7 +127,7 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
}

getYearName(date: LuxonDateTime): string {
return date.toFormat('yyyy');
return date.toFormat('yyyy', this._getOptions());
}

getFirstDayOfWeek(): number {
Expand All @@ -125,10 +139,12 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
}

clone(date: LuxonDateTime): LuxonDateTime {
return LuxonDateTime.fromObject(date.toObject());
return LuxonDateTime.fromObject(date.toObject(), this._getOptions());
}

createDate(year: number, month: number, date: number): LuxonDateTime {
const options = this._getOptions();

if (month < 0 || month > 11) {
throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`);
}
Expand All @@ -139,18 +155,20 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {

// Luxon uses 1-indexed months so we need to add one to the month.
const result = this._useUTC
? LuxonDateTime.utc(year, month + 1, date)
: LuxonDateTime.local(year, month + 1, date);
? LuxonDateTime.utc(year, month + 1, date, options)
: LuxonDateTime.local(year, month + 1, date, options);

if (!this.isValid(result)) {
throw Error(`Invalid date "${date}". Reason: "${result.invalidReason}".`);
}

return result.setLocale(this.locale);
return result;
}

today(): LuxonDateTime {
return (this._useUTC ? LuxonDateTime.utc() : LuxonDateTime.local()).setLocale(this.locale);
const options = this._getOptions();

return this._useUTC ? LuxonDateTime.utc(options) : LuxonDateTime.local(options);
}

parse(value: any, parseFormat: string | string[]): LuxonDateTime | null {
Expand Down Expand Up @@ -201,15 +219,15 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
}

addCalendarYears(date: LuxonDateTime, years: number): LuxonDateTime {
return date.plus({years}).setLocale(this.locale);
return date.reconfigure(this._getOptions()).plus({years});
}

addCalendarMonths(date: LuxonDateTime, months: number): LuxonDateTime {
return date.plus({months}).setLocale(this.locale);
return date.reconfigure(this._getOptions()).plus({months});
}

addCalendarDays(date: LuxonDateTime, days: number): LuxonDateTime {
return date.plus({days}).setLocale(this.locale);
return date.reconfigure(this._getOptions()).plus({days});
}

toIso8601(date: LuxonDateTime): string {
Expand Down Expand Up @@ -256,6 +274,7 @@ export class LuxonDateAdapter extends DateAdapter<LuxonDateTime> {
return {
zone: this._useUTC ? 'utc' : undefined,
locale: this.locale,
outputCalendar: this._defaultOutputCalendar,
};
}
}

0 comments on commit 439d6fc

Please sign in to comment.