128 lines
3.7 KiB
JavaScript
128 lines
3.7 KiB
JavaScript
// /src/composables/usePersianDate.js
|
||
import moment from 'jalali-moment';
|
||
|
||
export function usePersianDate() {
|
||
const toPersianDigits = (num) => {
|
||
if (num === null || num === undefined) return '';
|
||
const str = String(num);
|
||
const farsiDigits = ['۰', '۱', '۲', '۳', '۴', '۵', '۶', '۷', '۸', '۹'];
|
||
return str.replace(/\d/g, (x) => farsiDigits[parseInt(x)]);
|
||
};
|
||
|
||
const toLatinDigits = (str) => {
|
||
if (!str) return '';
|
||
const farsiDigits = [/۰/g, /۱/g, /۲/g, /۳/g, /۴/g, /۵/g, /۶/g, /۷/g, /۸/g, /۹/g];
|
||
let result = String(str);
|
||
for (let i = 0; i < 10; i++) {
|
||
result = result.replace(farsiDigits[i], String(i));
|
||
}
|
||
return result;
|
||
};
|
||
|
||
const parseToMoment = (value) => {
|
||
if (!value) return null;
|
||
if (value instanceof Date) {
|
||
if (Number.isNaN(value.getTime())) return null;
|
||
return moment.utc(value.toISOString());
|
||
}
|
||
const latin = toLatinDigits(String(value)).trim();
|
||
if (!latin) return null;
|
||
|
||
if (/^\d{4}-\d{2}-\d{2}T/.test(latin)) {
|
||
const m = moment.utc(latin);
|
||
return m.isValid() ? m : null;
|
||
}
|
||
|
||
const match = latin.match(/^(\d{3,4})[./\-](\d{1,2})[./\-](\d{1,2})/);
|
||
if (match) {
|
||
const year = parseInt(match[1], 10);
|
||
const month = parseInt(match[2], 10);
|
||
const day = parseInt(match[3], 10);
|
||
if (year >= 1200 && year <= 1599) {
|
||
const normalized = `${year}/${String(month).padStart(2, '0')}/${String(day).padStart(2, '0')}`;
|
||
const m = moment(normalized, 'jYYYY/jMM/jDD');
|
||
return m.isValid() ? m : null;
|
||
}
|
||
if (year >= 1900 && year <= 2200) {
|
||
const normalized = `${year}-${String(month).padStart(2, '0')}-${String(day).padStart(2, '0')}`;
|
||
const m = moment.utc(normalized, 'YYYY-MM-DD');
|
||
return m.isValid() ? m : null;
|
||
}
|
||
}
|
||
|
||
const m = moment.utc(latin);
|
||
return m.isValid() ? m : null;
|
||
};
|
||
|
||
const formatJalali = (date, formatStr = 'jYYYY/jMM/jDD') => {
|
||
if (!date) return '-';
|
||
try {
|
||
const m = parseToMoment(date);
|
||
if (!m || !m.isValid()) return '-';
|
||
return toPersianDigits(m.locale('fa').format(formatStr));
|
||
} catch (e) {
|
||
return '-';
|
||
}
|
||
};
|
||
|
||
const formatJalaliWithTime = (date) => {
|
||
if (!date) return '-';
|
||
try {
|
||
const latin = toLatinDigits(String(date)).trim();
|
||
if (/^\d{4}-\d{2}-\d{2}T/.test(latin) || date instanceof Date) {
|
||
return toPersianDigits(moment(date).locale('fa').format('jYYYY/jMM/jDD - HH:mm'));
|
||
}
|
||
return formatJalali(date, 'jYYYY/jMM/jDD - HH:mm');
|
||
} catch (e) {
|
||
return '-';
|
||
}
|
||
};
|
||
|
||
const toJalaliPickerValue = (value) => {
|
||
if (!value) return '';
|
||
try {
|
||
const m = parseToMoment(value);
|
||
if (!m || !m.isValid()) return '';
|
||
return toLatinDigits(m.locale('fa').format('jYYYY/jMM/jDD'));
|
||
} catch (e) {
|
||
return '';
|
||
}
|
||
};
|
||
|
||
const toGregorianIso = (jalaliValue) => {
|
||
if (!jalaliValue) return undefined;
|
||
try {
|
||
const m = parseToMoment(jalaliValue);
|
||
if (!m || !m.isValid()) return undefined;
|
||
return `${m.format('YYYY-MM-DD')}T00:00:00.000Z`;
|
||
} catch (e) {
|
||
return undefined;
|
||
}
|
||
};
|
||
|
||
const jalaliToIso = (jalaliStr) => toGregorianIso(jalaliStr) || null;
|
||
|
||
const getTodayJalali = (formatStr = 'jYYYY/jMM/jDD') => {
|
||
return toLatinDigits(moment().locale('fa').format(formatStr));
|
||
};
|
||
|
||
const getStartOfJalaliMonth = (formatStr = 'jYYYY/jMM/jDD') => {
|
||
return toLatinDigits(moment().startOf('jMonth').locale('fa').format(formatStr));
|
||
};
|
||
|
||
return {
|
||
toPersianDigits,
|
||
toLatinDigits,
|
||
parseToMoment,
|
||
formatJalali,
|
||
formatJalaliWithTime,
|
||
toJalaliPickerValue,
|
||
toGregorianIso,
|
||
jalaliToIso,
|
||
getTodayJalali,
|
||
getStartOfJalaliMonth
|
||
};
|
||
}
|
||
|
||
|