wikibase-sdk
Version:
utils functions to query a Wikibase instance and simplify its results
98 lines • 3.9 kB
JavaScript
export function wikibaseTimeToDateObject(wikibaseTime) {
// Also accept claim datavalue.value objects
if (typeof wikibaseTime === 'object') {
wikibaseTime = wikibaseTime.time;
}
const sign = wikibaseTime[0];
let [yearMonthDay, withinDay] = wikibaseTime.slice(1).split('T');
// Wikidata generates invalid ISO dates to indicate precision
// ex: +1990-00-00T00:00:00Z to indicate 1990 with year precision
yearMonthDay = yearMonthDay.replace(/-00/g, '-01');
const rest = `${yearMonthDay}T${withinDay}`;
return fullDateData(sign, rest);
}
const fullDateData = (sign, rest) => {
const year = rest.split('-')[0];
const needsExpandedYear = sign === '-' || year.length > 4;
return needsExpandedYear ? expandedYearDate(sign, rest, year) : new Date(rest);
};
const expandedYearDate = (sign, rest, year) => {
let date;
// Using ISO8601 expanded notation for negative years or positive
// years with more than 4 digits: adding up to 2 leading zeros
// when needed. Can't find the documentation again, but testing
// with `new Date(date)` gives a good clue of the implementation
if (year.length === 4) {
date = `${sign}00${rest}`;
}
else if (year.length === 5) {
date = `${sign}0${rest}`;
}
else {
date = sign + rest;
}
return new Date(date);
};
const toEpochTime = (wikibaseTime) => wikibaseTimeToDateObject(wikibaseTime).getTime();
const toISOString = (wikibaseTime) => wikibaseTimeToDateObject(wikibaseTime).toISOString();
// A date format that knows just three precisions:
// 'yyyy', 'yyyy-mm', and 'yyyy-mm-dd' (including negative and non-4 digit years)
// Should be able to handle the old and the new Wikidata time:
// - in the old one, units below the precision where set to 00
// - in the new one, those months and days are set to 01 in those cases,
// so when we can access the full claim object, we check the precision
// to recover the old format
const toSimpleDay = (wikibaseTime) => {
// Also accept claim datavalue.value objects, and actually prefer those,
// as we can check the precision
if (typeof wikibaseTime === 'object') {
const { time, precision } = wikibaseTime;
// Year precision
if (precision === 9)
wikibaseTime = time.replace('-01-01T', '-00-00T');
// Month precision
else if (precision === 10)
wikibaseTime = time.replace('-01T', '-00T');
else
wikibaseTime = time;
}
return wikibaseTime.split('T')[0]
// Remove positive years sign
.replace(/^\+/, '')
// Remove years padding zeros
.replace(/^(-?)0+/, '$1')
// Remove days if not included in the Wikidata date precision
.replace(/-00$/, '')
// Remove months if not included in the Wikidata date precision
.replace(/-00$/, '');
};
export const wikibaseTimeToEpochTime = toEpochTime;
export const wikibaseTimeToISOString = (value) => {
try {
return toISOString(value);
}
catch {
const { sign, yearMonthDay, withinDay } = recoverDateAfterError(value);
return `${sign}${yearMonthDay}T${withinDay}`;
}
};
export const wikibaseTimeToSimpleDay = (value) => {
try {
return toSimpleDay(value);
}
catch {
const { sign, yearMonthDay } = recoverDateAfterError(value);
return `${sign}${yearMonthDay}`;
}
};
function recoverDateAfterError(value) {
value = typeof value === 'string' ? value : value.time;
const sign = value[0];
let [yearMonthDay, withinDay] = value.slice(1).split('T');
if (!sign || !yearMonthDay || !withinDay) {
throw new Error('TimeInput is invalid: ' + JSON.stringify(value));
}
yearMonthDay = yearMonthDay.replace(/-00/g, '-01');
return { sign, yearMonthDay, withinDay };
}
//# sourceMappingURL=time.js.map