SmartParks_visitore/uni_modules/lime-shared/isDate/index.ts
2025-08-21 11:23:54 +08:00

189 lines
5.5 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// @ts-nocheck
/**
* 日期验证配置选项
*/
export type IsDateOptions = {
/** 日期格式字符串,默认 'YYYY/MM/DD' */
format ?: string;
/** 允许的分隔符数组,默认 ['/', '-'] */
delimiters ?: string[];
/** 是否严格匹配格式,默认 false */
strictMode ?: boolean;
}
/**
* 验证日期格式字符串是否合法
* @param format - 需要验证的格式字符串
* @returns 是否合法格式
*/
function isValidFormat(format : string) : boolean {
return /(^(y{4}|y{2})[年./-](m{1,2})[月./-](d{1,2}(日)?)$)|(^(m{1,2})[./-](d{1,2})[./-]((y{4}|y{2})$))|(^(d{1,2})[./-](m{1,2})[./-]((y{4}|y{2})$))/i.test(format);
}
/**
* 将日期部分和格式部分组合成键值对数组
* @param date - 分割后的日期部分数组
* @param format - 分割后的格式部分数组
* @returns 组合后的二维数组
*/
function zip(date : string[], format : string[]) : string[][] {
const zippedArr : string[][] = [];
const len = Math.max(date.length, format.length);
for (let i = 0; i < len; i++) {
const key = i < date.length ? date[i] : ''
const value = i < format.length ? format[i] : ''
zippedArr.push([key, value])
}
return zippedArr;
}
/** 验证日期对象 */
function validateDateObject(date : Date, strictMode : boolean) : boolean {
// #ifndef APP-ANDROID
return !strictMode && Object.prototype.toString.call(date) === '[object Date]' && !isNaN(date.getTime());
// #endif
// #ifdef APP-ANDROID
return !strictMode && !isNaN(date.getTime())
// #endif
}
function escapeRegExp(str: string): string {
return str//.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
function enhancedSplit(
str: string,
delimiters: string[]
): string[] {
// 构建动态分隔符正则表达式
const escapedDelimiters = delimiters.map(d => escapeRegExp(d));
const pattern = new RegExp(
`[${escapedDelimiters.join('')}]+`, // 匹配任意允许的分隔符
'g'
);
return str.split(pattern).filter(p => p != '');
}
/**
* 验证输入是否为有效日期
* @param input - 输入值,可以是字符串或 Date 对象
* @param options - 配置选项,可以是字符串(简写格式)或配置对象
* @returns 是否为有效日期
*
* @example
* isDate('2023/12/31'); // true
* isDate(new Date()); // true
* isDate('02-29-2023', { strictMode: true }); // false2023年不是闰年
*/
export function isDate(input : Date, options ?: IsDateOptions) : boolean;
export function isDate(input : string, options ?: string | IsDateOptions) : boolean;
export function isDate(input : string | Date, options : string | IsDateOptions | null = null) : boolean {
// 处理参数重载:允许第二个参数直接传格式字符串
// Date对象验证
let format = 'YYYY/MM/DD'
let delimiters = ['/', '-']
let strictMode = false
if (options != null) {
if (typeof options == 'string') {
format = options as string
} else {
format = (options as IsDateOptions).format ?? format
delimiters = (options as IsDateOptions).delimiters ?? delimiters
strictMode = (options as IsDateOptions).strictMode ?? strictMode
}
}
if (input instanceof Date) {
return validateDateObject(input, strictMode);
}
// 字符串类型验证
if (!isValidFormat(format)) return false;
// 严格模式长度检查
if (strictMode && input.length != format.length) {
return false;
}
// 获取格式中的分隔符
const formatDelimiter = delimiters.find((d) : boolean => format.indexOf(d) != -1);
// 获取实际使用的分隔符
const dateDelimiter = strictMode
? formatDelimiter
: delimiters.find((d) : boolean => input.indexOf(d) != -1);
// 分割日期和格式
const dateParts = strictMode ? enhancedSplit(input, delimiters) : input.split(dateDelimiter ?? '');
const formatParts = strictMode ? enhancedSplit(format.toLowerCase(), delimiters) : format.toLowerCase().split(formatDelimiter ?? '');
// 组合成键值对
const dateAndFormat = zip(dateParts, formatParts);
const dateObj = new Map<string, string>();
// 解析日期组成部分
for (const [dateWord, formatWord] of dateAndFormat) {
if (dateWord == '' || formatWord == '' || dateWord.length != formatWord.length) {
return false;
}
dateObj.set(formatWord.charAt(0), dateWord)
}
// 年份处理
let fullYear = dateObj.get('y');
if (fullYear == null) return false;
// 检查年份前导负号
if (fullYear.startsWith('-')) return false;
// 两位年份转四位
if (fullYear.length == 2) {
const parsedYear = parseInt(fullYear, 10);
if (isNaN(parsedYear)) {
return false;
}
const currentYear = new Date().getFullYear();
const century = currentYear - (currentYear % 100);
fullYear = (parseInt(fullYear, 10) < (currentYear % 100))
? `${century + 100 + parseInt(fullYear, 10)}`
: `${century + parseInt(fullYear, 10)}`;
}
// 月份补零
const month = dateObj.get('m')?.padStart(2, '0') ?? '';
// 日期补零
const day = dateObj.get('d')?.padStart(2, '0') ?? '';
const isoDate = `${fullYear}-${month}-${day}T00:00:00.000Z`;
// return new Date(time).getDate() == parseInt(day);
// 构造 ISO 日期字符串验证
try {
// #ifndef APP-ANDROID
const date = new Date(isoDate);
return date.getUTCDate() === parseInt(day, 10) &&
(date.getUTCMonth() + 1) === parseInt(month, 10) &&
date.getUTCFullYear() === parseInt(fullYear, 10);
// #endif
// #ifdef APP-ANDROID
const date = new Date(isoDate);
return date.getDate() == parseInt(day, 10) &&
(date.getMonth() + 1) == parseInt(month, 10) &&
date.getFullYear() == parseInt(fullYear, 10);
// #endif
} catch {
return false;
}
}