This commit is contained in:
+183
@@ -0,0 +1,183 @@
|
||||
// map from unicode eastern arabic number characters to arabic numbers
|
||||
const EASTERN_ARABIC_DIGIT_MAP = {
|
||||
'\\u0660': '0',
|
||||
'\\u0661': '1',
|
||||
'\\u0662': '2',
|
||||
'\\u0663': '3',
|
||||
'\\u0664': '4',
|
||||
'\\u0665': '5',
|
||||
'\\u0666': '6',
|
||||
'\\u0667': '7',
|
||||
'\\u0668': '8',
|
||||
'\\u0669': '9'
|
||||
};
|
||||
|
||||
/**
|
||||
* Escapes the given string so it can be safely used in a regexp.
|
||||
*
|
||||
* @param {string} string
|
||||
* @return {string}
|
||||
*/
|
||||
function escapeRegExp(string) {
|
||||
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses eastern arabic number characters to arabic numbers (0-9)
|
||||
*
|
||||
* @param {string} digits
|
||||
* @return {string}
|
||||
*/
|
||||
function parseEasternArabicDigits(digits) {
|
||||
return digits.replace(/[\u0660-\u0669]/g, function (char) {
|
||||
const unicode = '\\u0' + char.charCodeAt(0).toString(16);
|
||||
return EASTERN_ARABIC_DIGIT_MAP[unicode];
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @param {Date} testTime
|
||||
* @return {string | null}
|
||||
*/
|
||||
function getAmOrPmString(locale, testTime) {
|
||||
const testTimeString = testTime.toLocaleTimeString(locale);
|
||||
|
||||
// AM/PM string is anything from one letter in eastern arabic to standard two letters,
|
||||
// to having space in between, dots ...
|
||||
// cannot disqualify whitespace since some locales use a. m. / p. m.
|
||||
// TODO when more scripts support is added (than Arabic), need to exclude those numbers too
|
||||
const amOrPmRegExp = /[^\d\u0660-\u0669]/;
|
||||
|
||||
const matches =
|
||||
// In most locales, the time ends with AM/PM:
|
||||
testTimeString.match(new RegExp(`${amOrPmRegExp.source}+$`, 'g')) ||
|
||||
// In some locales, the time starts with AM/PM e.g in Chinese:
|
||||
testTimeString.match(new RegExp(`^${amOrPmRegExp.source}+`, 'g'));
|
||||
|
||||
return matches && matches[0].trim();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @return {string | null}
|
||||
*/
|
||||
export function getSeparator(locale) {
|
||||
let timeString = TEST_PM_TIME.toLocaleTimeString(locale);
|
||||
|
||||
// Since the next regex picks first non-number-whitespace,
|
||||
// need to discard possible PM from beginning (eg. chinese locale)
|
||||
const pmString = getPmString(locale);
|
||||
if (pmString && timeString.startsWith(pmString)) {
|
||||
timeString = timeString.replace(pmString, '');
|
||||
}
|
||||
|
||||
const matches = timeString.match(/[^\u0660-\u0669\s\d]/);
|
||||
return matches && matches[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for either an AM or PM token in the given time string
|
||||
* depending on what is provided in `amOrPmString`.
|
||||
*
|
||||
* The search is case and space insensitive.
|
||||
*
|
||||
* @example
|
||||
* `searchAmOrPmToken('1 P M', 'PM')` => `'P M'`
|
||||
*
|
||||
* @example
|
||||
* `searchAmOrPmToken('1 a.m.', 'A. M.')` => `a.m.`
|
||||
*
|
||||
* @param {string} timeString
|
||||
* @param {string} amOrPmString
|
||||
* @return {string | null}
|
||||
*/
|
||||
export function searchAmOrPmToken(timeString, amOrPmString) {
|
||||
if (!amOrPmString) return null;
|
||||
|
||||
// Create a regexp string for searching for AM/PM without space-sensitivity.
|
||||
const tokenRegExpString = amOrPmString.split(/\s*/).map(escapeRegExp).join('\\s*');
|
||||
|
||||
// Create a regexp without case-sensitivity.
|
||||
const tokenRegExp = new RegExp(tokenRegExpString, 'i');
|
||||
|
||||
// Match the regexp against the time string.
|
||||
const tokenMatches = timeString.match(tokenRegExp);
|
||||
if (tokenMatches) {
|
||||
return tokenMatches[0];
|
||||
}
|
||||
}
|
||||
|
||||
export const TEST_PM_TIME = new Date('August 19, 1975 23:15:30');
|
||||
|
||||
export const TEST_AM_TIME = new Date('August 19, 1975 05:15:30');
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @return {string}
|
||||
*/
|
||||
export function getPmString(locale) {
|
||||
return getAmOrPmString(locale, TEST_PM_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} locale
|
||||
* @return {string}
|
||||
*/
|
||||
export function getAmString(locale) {
|
||||
return getAmOrPmString(locale, TEST_AM_TIME);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} digits
|
||||
* @return {number}
|
||||
*/
|
||||
export function parseDigitsIntoInteger(digits) {
|
||||
return parseInt(parseEasternArabicDigits(digits));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} milliseconds
|
||||
* @return {number}
|
||||
*/
|
||||
export function parseMillisecondsIntoInteger(milliseconds) {
|
||||
milliseconds = parseEasternArabicDigits(milliseconds);
|
||||
// digits are either .1 .01 or .001 so need to "shift"
|
||||
if (milliseconds.length === 1) {
|
||||
milliseconds += '00';
|
||||
} else if (milliseconds.length === 2) {
|
||||
milliseconds += '0';
|
||||
}
|
||||
return parseInt(milliseconds);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string} timeString
|
||||
* @param {number} milliseconds
|
||||
* @param {string} amString
|
||||
* @param {string} pmString
|
||||
* @return {string}
|
||||
*/
|
||||
export function formatMilliseconds(timeString, milliseconds, amString, pmString) {
|
||||
// might need to inject milliseconds between seconds and AM/PM
|
||||
let cleanedTimeString = timeString;
|
||||
if (timeString.endsWith(amString)) {
|
||||
cleanedTimeString = timeString.replace(' ' + amString, '');
|
||||
} else if (timeString.endsWith(pmString)) {
|
||||
cleanedTimeString = timeString.replace(' ' + pmString, '');
|
||||
}
|
||||
if (milliseconds) {
|
||||
let millisecondsString = milliseconds < 10 ? '0' : '';
|
||||
millisecondsString += milliseconds < 100 ? '0' : '';
|
||||
millisecondsString += milliseconds;
|
||||
cleanedTimeString += '.' + millisecondsString;
|
||||
} else {
|
||||
cleanedTimeString += '.000';
|
||||
}
|
||||
if (timeString.endsWith(amString)) {
|
||||
cleanedTimeString = cleanedTimeString + ' ' + amString;
|
||||
} else if (timeString.endsWith(pmString)) {
|
||||
cleanedTimeString = cleanedTimeString + ' ' + pmString;
|
||||
}
|
||||
return cleanedTimeString;
|
||||
}
|
||||
Reference in New Issue
Block a user