libs/core/dynamic-form/date/src/iso-date-adapter/iso-date-adapter-testing.ts
NxDateAdapter
Methods |
constructor(dateLocale: string)
|
||||||
Parameters :
|
addCalendarDays |
addCalendarDays(date: string, days: number)
|
Returns :
string
|
addCalendarMonths |
addCalendarMonths(date: string, months: number)
|
Returns :
string
|
addCalendarYears |
addCalendarYears(date: string, years: number)
|
Returns :
string
|
clone | ||||||
clone(date: string)
|
||||||
Parameters :
Returns :
string
|
createDate |
createDate(year: number, month: number, date: number)
|
Returns :
string
|
deserialize | ||||||
deserialize(value: any)
|
||||||
Parameters :
Returns :
string | null
|
format |
format(date: string, displayFormat: any)
|
Returns :
string
|
getDate | ||||||
getDate(date: string)
|
||||||
Parameters :
Returns :
number
|
getDateNames |
getDateNames()
|
Returns :
string[]
|
getDayOfWeek | ||||||
getDayOfWeek(date: string)
|
||||||
Parameters :
Returns :
number
|
getDayOfWeekNames | ||||||
getDayOfWeekNames(style: "long" | "short" | "narrow")
|
||||||
Parameters :
Returns :
string[]
|
getFirstDayOfWeek |
getFirstDayOfWeek()
|
Returns :
number
|
getMonth | ||||||
getMonth(date: string)
|
||||||
Parameters :
Returns :
number
|
getMonthNames | ||||||
getMonthNames(style: "long" | "short" | "narrow")
|
||||||
Parameters :
Returns :
string[]
|
getNumDaysInMonth | ||||||
getNumDaysInMonth(date: string)
|
||||||
Parameters :
Returns :
number
|
getYear | ||||||
getYear(date: string)
|
||||||
Parameters :
Returns :
number
|
getYearName | ||||||
getYearName(date: string)
|
||||||
Parameters :
Returns :
string
|
invalid |
invalid()
|
Returns :
string
|
isDateInstance | ||||||
isDateInstance(obj: any)
|
||||||
Parameters :
Returns :
boolean
|
isValid | ||||||
isValid(date: string | Dayjs)
|
||||||
Parameters :
Returns :
boolean
|
normalizeFormat | ||||||
normalizeFormat(format: string | string[])
|
||||||
if the given formats include a localized format we have to map it manually to a dayjs format as dayjs recognizes locale format only for formatting not for parsing see https://github.com/iamkun/dayjs/issues/694#issuecomment-543209946
Parameters :
Returns :
string[]
|
parse |
parse(value: any, format: string | string[], strict: boolean)
|
Returns :
string | null
|
setLocale | ||||||
setLocale(locale: string)
|
||||||
Parameters :
Returns :
void
|
today |
today()
|
Returns :
string
|
toIso8601 | ||||||
toIso8601(date: string)
|
||||||
Parameters :
Returns :
string
|
import { NX_DATE_LOCALE, NxDateAdapter } from '@aposin/ng-aquila/datefield';
import { pad } from '@aposin/ng-aquila/utils';
import { Inject, Optional } from '@angular/core';
import dayjs, { Dayjs } from 'dayjs';
import customParseFormat from 'dayjs/plugin/customParseFormat';
import localeData from 'dayjs/plugin/localeData';
import localizedFormat from 'dayjs/plugin/localizedFormat';
import utc from 'dayjs/plugin/utc';
dayjs.extend(localeData);
dayjs.extend(customParseFormat);
dayjs.extend(localizedFormat);
dayjs.extend(utc);
const ISO_STRING_FORMAT = 'YYYY-MM-DD';
const ISO_REGEX = /^([0-9]{4})(-?)(1[0-2]|0[1-9])\2(3[01]|0[1-9]|[12][0-9])$/;
/** 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;
}
/**
* @docs-private
*/
export class DfIsoDateAdapterTesting extends NxDateAdapter<string> {
private _localeData:
| {
firstDayOfWeek: number;
longMonths: string[];
shortMonths: string[];
dates: string[];
longDaysOfWeek: string[];
shortDaysOfWeek: string[];
narrowDaysOfWeek: string[];
}
| undefined;
constructor(@Optional() @Inject(NX_DATE_LOCALE) dateLocale: string) {
super();
this.setLocale(dateLocale || dayjs.locale());
}
toIso8601(date: string): string {
return dayjs.utc(date).format();
}
override deserialize(value: any): string | null {
let date: string | Dayjs | undefined;
// TODO should we accept that or only take strings?
if (value instanceof Date) {
date = dayjs(value).locale(this.locale);
}
if (typeof value === 'string') {
if (!value) {
return null;
}
date = dayjs(value).locale(this.locale);
}
if (date && this.isValid(date)) {
return dayjs(date).locale(this.locale).format(ISO_STRING_FORMAT);
}
return super.deserialize(value);
}
format(date: string, displayFormat: any): string {
return this._createDayjs(date).format(displayFormat);
}
/**
* if the given formats include a localized format we have to map
* it manually to a dayjs format as dayjs recognizes locale
* format only for formatting not for parsing
* see https://github.com/iamkun/dayjs/issues/694#issuecomment-543209946
*/
normalizeFormat(format: string | string[]): string[] {
const availableLocalFormats = dayjs.Ls[this.locale]?.formats;
if (!availableLocalFormats) {
throw new Error(
`NxIsoDateAdapter: The used locale "${this.locale}" is not available in this day.js instance. Please make sure the locale is imported.`
);
}
let normalizedFormat = format;
if (!Array.isArray(normalizedFormat)) {
normalizedFormat = [normalizedFormat];
}
normalizedFormat = normalizedFormat.map((formatString) => {
if (Object.keys(availableLocalFormats).indexOf(formatString) !== -1) {
return (availableLocalFormats as any)[formatString];
}
return formatString;
});
return normalizedFormat;
}
parse(value: any, format: string | string[], strict: boolean): string | null {
let obj: Dayjs | undefined;
const normalizedFormats = this.normalizeFormat(format);
if (value && typeof value === 'string') {
if (strict) {
obj = dayjs(value, normalizedFormats, this.locale, true);
} else {
// The non strict parsing of day.js is rather strict when it comes to separators.
// For example, this format: YYYY-MM-DD still requires the user to type in the -
// To get a little closer to the behavior of momentjs, the following code extends
// the list of given formats with versions were all the separators were removed
const formatsWithoutSeparators = [...normalizedFormats].map((normalizedformat) => {
return normalizedformat.replace(/[^\w]/g, '');
});
obj = dayjs(value, [...formatsWithoutSeparators, ...normalizedFormats], this.locale, false);
}
}
if (obj?.isValid() === false) {
return '';
}
return obj ? obj.format(ISO_STRING_FORMAT) : null;
}
isValid(date: string | Dayjs): boolean {
return dayjs(date).isValid();
}
clone(date: string): string {
return date;
}
isDateInstance(obj: any): boolean {
return obj === '' || (typeof obj === 'string' && ISO_REGEX.test(obj));
}
invalid(): string {
return '';
}
getYear(date: string): number {
return this._createDayjs(date).year();
}
getMonth(date: string): number {
return this._createDayjs(date).month();
}
getDate(date: string): number {
return this._createDayjs(date).date();
}
getYearName(date: string): string {
return this._createDayjs(date).format('YYYY');
}
createDate(year: number, month: number, date: number): string {
// Check for invalid month and date (except upper bound on date which we have to check after
// creating the Date).
if (month < 0 || month > 11) {
throw Error(`Invalid month index "${month}". Month index has to be between 0 and 11.`);
}
if (date < 1) {
throw Error(`Invalid date "${date}". Date has to be greater than 0.`);
}
// dayjs adds overflows up instead of creating invalid dates so we have to check that here
const obj = this._createDayjs(this._createString(year, month + 1, date));
// Check that the date wasn't above the upper bound for the month, causing the month to overflow
if (obj.month() !== month || obj.year() !== year) {
throw Error(`Invalid date "${date}" for month with index "${month}".`);
}
return obj.format(ISO_STRING_FORMAT);
}
getNumDaysInMonth(date: string): number {
return this._createDayjs(date).daysInMonth();
}
getDateNames(): string[] {
return this._localeData?.dates || [];
}
getDayOfWeek(date: string): number {
return this._createDayjs(date).day();
}
getFirstDayOfWeek(): number {
return this._localeData?.firstDayOfWeek || 0;
}
getMonthNames(style: 'long' | 'short' | 'narrow'): string[] {
const monthNames =
style === 'long' ? this._localeData?.longMonths : this._localeData?.shortMonths;
return monthNames || [];
}
today(): string {
return dayjs().format(ISO_STRING_FORMAT);
}
addCalendarMonths(date: string, months: number): string {
return this._createDayjs(date).add(months, 'M').format(ISO_STRING_FORMAT);
}
addCalendarYears(date: string, years: number): string {
return this._createDayjs(date).add(years, 'y').format(ISO_STRING_FORMAT);
}
addCalendarDays(date: string, days: number): string {
return this._createDayjs(date).add(days, 'd').format(ISO_STRING_FORMAT);
}
getDayOfWeekNames(style: 'long' | 'short' | 'narrow'): string[] {
if (style === 'long') {
return this._localeData?.longDaysOfWeek || [];
}
if (style === 'short') {
return this._localeData?.shortDaysOfWeek || [];
}
return this._localeData?.narrowDaysOfWeek || [];
}
override setLocale(locale: string) {
const data = dayjs().locale(locale).localeData();
this._localeData = {
firstDayOfWeek: data.firstDayOfWeek(),
longMonths: data.months(),
shortMonths: data.monthsShort(),
dates: range(31, (i) => this._createDayjs(this.createDate(2017, 0, i + 1)).format('D')),
longDaysOfWeek: data.weekdays(),
shortDaysOfWeek: data.weekdaysShort(),
narrowDaysOfWeek: data.weekdaysMin()
};
super.setLocale(locale);
}
private _createDayjs(value: string) {
return dayjs.utc(value).locale(this.locale);
}
private _createString(year: number, month: number, date: number) {
return `${year}-${pad(month.toString())}-${pad(date.toString())}`;
}
}