Skip to content

Commit

Permalink
[pickers] Reuse AdapterDateFnsBase in Jalali adapters (mui#13075)
Browse files Browse the repository at this point in the history
  • Loading branch information
LukasTy authored and DungTiger committed Jul 23, 2024
1 parent d7c5101 commit 5658246
Show file tree
Hide file tree
Showing 6 changed files with 50 additions and 315 deletions.
6 changes: 6 additions & 0 deletions packages/x-date-pickers/src/AdapterDateFns/AdapterDateFns.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,12 @@ import { AdapterDateFnsBase } from '../AdapterDateFnsBase';

type DateFnsLocale = typeof defaultLocale;

declare module '@mui/x-date-pickers/models' {
interface PickerValidDateLookup {
'date-fns': Date;
}
}

/**
* Based on `@date-io/date-fns`
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,9 @@ type DateFnsAdapterBaseOptions<DateFnsLocale extends DateFnsLocaleBase> = MakeRe
'locale'
> & {
longFormatters: Record<'p' | 'P', (token: string, formatLong: any) => string>;
lib?: string;
};

declare module '@mui/x-date-pickers/models' {
interface PickerValidDateLookup {
'date-fns': Date;
}
}

/**
* Based on `@date-io/date-fns`
*
Expand Down Expand Up @@ -168,7 +163,7 @@ export class AdapterDateFnsBase<DateFnsLocale extends DateFnsLocaleBase>

public isTimezoneCompatible = false;

public lib = 'date-fns';
public lib: string;

public locale: DateFnsLocale;

Expand All @@ -181,10 +176,11 @@ export class AdapterDateFnsBase<DateFnsLocale extends DateFnsLocaleBase>
public longFormatters: DateFnsAdapterBaseOptions<DateFnsLocale>['longFormatters'];

constructor(props: DateFnsAdapterBaseOptions<DateFnsLocale>) {
const { locale, formats, longFormatters } = props;
const { locale, formats, longFormatters, lib } = props;
this.locale = locale;
this.formats = { ...defaultFormats, ...formats };
this.longFormatters = longFormatters;
this.lib = lib || 'date-fns';
}

public date = <T extends string | null | undefined>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,27 +10,26 @@ import {
import { enUS } from 'date-fns/locale';
import faIR from 'date-fns-jalali/locale/fa-IR';
import faJalaliIR from 'date-fns-jalali/locale/fa-jalali-IR';
import { AdapterMomentJalaali } from '@mui/x-date-pickers/AdapterMomentJalaali';
import { AdapterFormats } from '@mui/x-date-pickers/models';

describe('<AdapterDateFnsJalali />', () => {
describeJalaliAdapter(AdapterDateFnsJalali, {});

describe('Adapter localization', () => {
it('Formatting', () => {
const adapter = new AdapterMomentJalaali();
const adapter = new AdapterDateFnsJalali();

const expectDate = (format: keyof AdapterFormats, expectedWithFaIR: string) => {
const date = adapter.date('2020-02-01T23:44:00.000Z')!;

expect(adapter.format(date, format)).to.equal(expectedWithFaIR);
};

expectDate('fullDate', '۱۳۹۸، Bahman ۱م');
expectDate('keyboardDate', '۱۳۹۸/۱۱/۱۲');
expectDate('keyboardDateTime', '۱۳۹۸/۱۱/۱۲ ۲۳:۴۴');
expectDate('keyboardDateTime12h', '۱۳۹۸/۱۱/۱۲ ۱۱:۴۴ بعد از ظهر');
expectDate('keyboardDateTime24h', '۱۳۹۸/۱۱/۱۲ ۲۳:۴۴');
expectDate('fullDate', '12-ام بهمن 1398');
expectDate('keyboardDate', '1398/11/12');
expectDate('keyboardDateTime', '1398/11/12 11:44 ب.ظ.');
expectDate('keyboardDateTime12h', '1398/11/12 11:44 ب.ظ.');
expectDate('keyboardDateTime24h', '1398/11/12 23:44');
});
});

Expand Down
164 changes: 14 additions & 150 deletions packages/x-date-pickers/src/AdapterDateFnsJalali/AdapterDateFnsJalali.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,81 +44,11 @@ import isWithinInterval from 'date-fns-jalali/isWithinInterval';
import defaultLocale from 'date-fns-jalali/locale/fa-IR';
// @ts-ignore
import longFormatters from 'date-fns-jalali/_lib/format/longFormatters';
import {
AdapterFormats,
AdapterOptions,
DateBuilderReturnType,
FieldFormatTokenMap,
MuiPickersAdapter,
} from '../models';
import { AdapterFormats, AdapterOptions, MuiPickersAdapter } from '../models';
import { AdapterDateFnsBase } from '../AdapterDateFnsBase';

type DateFnsLocale = typeof defaultLocale;

const formatTokenMap: FieldFormatTokenMap = {
// Year
y: { sectionType: 'year', contentType: 'digit', maxLength: 4 },
yy: 'year',
yyy: { sectionType: 'year', contentType: 'digit', maxLength: 4 },
yyyy: 'year',

// Month
M: { sectionType: 'month', contentType: 'digit', maxLength: 2 },
MM: 'month',
MMMM: { sectionType: 'month', contentType: 'letter' },
MMM: { sectionType: 'month', contentType: 'letter' },
L: { sectionType: 'month', contentType: 'digit', maxLength: 2 },
LL: 'month',
LLL: { sectionType: 'month', contentType: 'letter' },
LLLL: { sectionType: 'month', contentType: 'letter' },

// Day of the month
d: { sectionType: 'day', contentType: 'digit', maxLength: 2 },
dd: 'day',
do: { sectionType: 'day', contentType: 'digit-with-letter' },

// Day of the week
E: { sectionType: 'weekDay', contentType: 'letter' },
EE: { sectionType: 'weekDay', contentType: 'letter' },
EEE: { sectionType: 'weekDay', contentType: 'letter' },
EEEE: { sectionType: 'weekDay', contentType: 'letter' },
EEEEE: { sectionType: 'weekDay', contentType: 'letter' },
i: { sectionType: 'weekDay', contentType: 'digit', maxLength: 1 },
ii: 'weekDay',
iii: { sectionType: 'weekDay', contentType: 'letter' },
iiii: { sectionType: 'weekDay', contentType: 'letter' },
e: { sectionType: 'weekDay', contentType: 'digit', maxLength: 1 },
ee: 'weekDay',
eee: { sectionType: 'weekDay', contentType: 'letter' },
eeee: { sectionType: 'weekDay', contentType: 'letter' },
eeeee: { sectionType: 'weekDay', contentType: 'letter' },
eeeeee: { sectionType: 'weekDay', contentType: 'letter' },
c: { sectionType: 'weekDay', contentType: 'digit', maxLength: 1 },
cc: 'weekDay',
ccc: { sectionType: 'weekDay', contentType: 'letter' },
cccc: { sectionType: 'weekDay', contentType: 'letter' },
ccccc: { sectionType: 'weekDay', contentType: 'letter' },
cccccc: { sectionType: 'weekDay', contentType: 'letter' },

// Meridiem
a: 'meridiem',
aa: 'meridiem',
aaa: 'meridiem',

// Hours
H: { sectionType: 'hours', contentType: 'digit', maxLength: 2 },
HH: 'hours',
h: { sectionType: 'hours', contentType: 'digit', maxLength: 2 },
hh: 'hours',

// Minutes
m: { sectionType: 'minutes', contentType: 'digit', maxLength: 2 },
mm: 'minutes',

// Seconds
s: { sectionType: 'seconds', contentType: 'digit', maxLength: 2 },
ss: 'seconds',
};

const defaultFormats: AdapterFormats = {
year: 'yyyy',
month: 'LLLL',
Expand Down Expand Up @@ -191,21 +121,10 @@ declare module '@mui/x-date-pickers/models' {
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
export class AdapterDateFnsJalali implements MuiPickersAdapter<Date, DateFnsLocale> {
public isMUIAdapter = true;

public isTimezoneCompatible = false;

public lib = 'date-fns-jalali';

public locale?: DateFnsLocale;

public formats: AdapterFormats;

public formatTokenMap = formatTokenMap;

public escapedCharacters = { start: "'", end: "'" };

export class AdapterDateFnsJalali
extends AdapterDateFnsBase<DateFnsLocale>
implements MuiPickersAdapter<Date, DateFnsLocale>
{
constructor({ locale, formats }: AdapterOptions<DateFnsLocale, never> = {}) {
if (typeof addDays !== 'function') {
throw new Error(
Expand All @@ -215,39 +134,16 @@ export class AdapterDateFnsJalali implements MuiPickersAdapter<Date, DateFnsLoca
].join('\n'),
);
}
this.locale = locale;
this.formats = { ...defaultFormats, ...formats };
super({
locale: locale ?? defaultLocale,
// some formats are different in jalali adapter,
// this ensures that `AdapterDateFnsBase` formats are overridden
formats: { ...defaultFormats, ...formats },
longFormatters,
lib: 'date-fns-jalali',
});
}

public date = <T extends string | null | undefined>(
value?: T,
): DateBuilderReturnType<T, Date> => {
type R = DateBuilderReturnType<T, Date>;
if (typeof value === 'undefined') {
return <R>new Date();
}

if (value === null) {
return <R>null;
}

return <R>new Date(value);
};

public getInvalidDate = () => new Date('Invalid Date');

public getTimezone = (): string => {
return 'default';
};

public setTimezone = (value: Date): Date => {
return value;
};

public toJsDate = (value: Date) => {
return value;
};

public parse = (value: string, format: string) => {
if (value === '') {
return null;
Expand All @@ -260,34 +156,6 @@ export class AdapterDateFnsJalali implements MuiPickersAdapter<Date, DateFnsLoca
return this.locale?.code || 'fa-IR';
};

// Note: date-fns input types are more lenient than this adapter, so we need to expose our more
// strict signature and delegate to the more lenient signature. Otherwise, we have downstream type errors upon usage.
public is12HourCycleInCurrentLocale = () => {
if (this.locale) {
return /a/.test(this.locale.formatLong!.time());
}

// By default, date-fns-jalali is using fa-IR locale with am/pm enabled
return true;
};

public expandFormat = (format: string) => {
// @see https://github.com/date-fns/date-fns/blob/master/src/format/index.js#L31
const longFormatRegexp = /P+p+|P+|p+|''|'(''|[^'])+('|$)|./g;
const locale = this.locale ?? defaultLocale;
return format
.match(longFormatRegexp)!
.map((token) => {
const firstCharacter = token[0];
if (firstCharacter === 'p' || firstCharacter === 'P') {
const longFormatter = longFormatters[firstCharacter];
return longFormatter(token, locale.formatLong, {});
}
return token;
})
.join('');
};

public isValid = (value: Date | null) => {
if (value == null) {
return false;
Expand Down Expand Up @@ -510,10 +378,6 @@ export class AdapterDateFnsJalali implements MuiPickersAdapter<Date, DateFnsLoca
return getWeek(date, { locale: this.locale });
};

public getDayOfWeek(value: Date) {
return value.getDay() + 1;
}

public getYearRange = ([start, end]: [Date, Date]) => {
const startDate = this.startOfYear(start);
const endDate = this.endOfYear(end);
Expand Down
Loading

0 comments on commit 5658246

Please sign in to comment.