aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/components/InfoModal.vue18
-rw-r--r--src/lib.ts80
-rw-r--r--tests/lib.test.ts96
3 files changed, 141 insertions, 53 deletions
diff --git a/src/components/InfoModal.vue b/src/components/InfoModal.vue
index d2ac425..0b46be0 100644
--- a/src/components/InfoModal.vue
+++ b/src/components/InfoModal.vue
@@ -7,7 +7,14 @@
<h1 class="text-center text-xl font-bold pt-2 pb-1 md:text-2xl md:pt-3 md:pb-1">
{{event.title}}
</h1>
- <p class="text-center text-sm md:text-base">{{datesDisplayStr}}</p>
+ <!-- Time Display -->
+ <div class="text-center text-sm md:text-base">
+ {{datesDisplayStrs.length == 1 ? 'Time' : 'Start'}}: {{datesDisplayStrs[0]}}
+ </div>
+ <div v-if="datesDisplayStrs.length > 1" class="text-center text-sm md:text-base">
+ End: {{datesDisplayStrs[1]}}
+ </div>
+ <!-- Main content -->
<div class="border-t border-stone-400 p-2 md:p-3">
<div class="mt-1 mr-2 md:mb-2 md:mr-4 md:float-left">
<!-- Image -->
@@ -75,7 +82,7 @@ import SCollapsible from './SCollapsible.vue';
import CloseIcon from './icon/CloseIcon.vue';
import DownIcon from './icon/DownIcon.vue';
import ExternalLinkIcon from './icon/ExternalLinkIcon.vue';
-import {EventInfo, boundedDateToStr, getImagePath} from '../lib';
+import {EventInfo, eventDatesToStrings, getImagePath} from '../lib';
import {useStore} from '../store';
// Refs
@@ -93,11 +100,8 @@ const emit = defineEmits(['close']);
// For data display
const event = computed(() => props.eventInfo.event)
-const datesDisplayStr = computed(() => {
- const startStr = boundedDateToStr(event.value.start, event.value.startUpper);
- const endStr = event.value.end == null ? null : boundedDateToStr(event.value.end, event.value.endUpper);
- return 'Start: ' + startStr + (endStr == null ? '' : ', End: ' + endStr);
-});
+const datesDisplayStrs = computed(
+ () => eventDatesToStrings(event.value.start, event.value.startUpper, event.value.end, event.value.endUpper));
function licenseToUrl(license: string){
license = license.toLowerCase().replaceAll('-', ' ');
if (license == 'cc0'){
diff --git a/src/lib.ts b/src/lib.ts
index 6833520..52413bb 100644
--- a/src/lib.ts
+++ b/src/lib.ts
@@ -261,9 +261,9 @@ export class HistDate {
} else {
return `${this.year}`; // eg: 2010
}
- } else { // eg: 2nd Mar 1710 BC (OS)
- let bcSuffix = this.year < 0 ? ' BC' : (this.year < 1500 ? ' AD' : '');
- let calStr = this.gcal ? '' : ' (OS)';
+ } else { // eg: 2nd Mar 1710 BC (O.S.)
+ const bcSuffix = this.year < 0 ? ' BC' : (this.year < 1500 ? ' AD' : '');
+ const calStr = this.gcal ? '' : ' (O.S.)';
return `${intToOrdinal(this.day)} ${MONTH_NAMES[this.month-1]} ${Math.abs(this.year)}${bcSuffix}${calStr}`;
}
}
@@ -312,7 +312,7 @@ export function boundedDateToStr(start: HistDate, end: HistDate | null) : string
const startMatch = dateRegex.exec(startStr)!;
const endMatch = dateRegex.exec(endStr)!;
if (startMatch[2] == endMatch[2]){ // Same billion/million/thousand scale
- let startZeros = getNumTrailingZeros(start.year);
+ const startZeros = getNumTrailingZeros(start.year);
if (startZeros >= 4 && end.year == start.year + 10 ** startZeros - 1
|| (start.year - 1) % 1e3 == 0 && end.year == start.year + 999){
return `About ${startStr}`; // Includes cases like -20_000 to -10_001 and -21999 to -21000
@@ -322,23 +322,23 @@ export function boundedDateToStr(start: HistDate, end: HistDate | null) : string
return `${startMatch[1]} ${startMatch[2]} to ${endMatch[1]} ${endMatch[2]} years ago`;
}
} else if (moduloPositive(start.year, 1000) == 1 && end.year == start.year + 999){ // eg: 2nd millenium
- let ordinal = intToOrdinal(Math.abs(start.year - 1) / 1000 + (start.year > 0 ? 1 : 0));
+ const ordinal = intToOrdinal(Math.abs(start.year - 1) / 1000 + (start.year > 0 ? 1 : 0));
return ordinal + ' millenium' + (start.year < 0 ? ' BC' : '');
} else if (moduloPositive(start.year, 100) == 1 && end.year == start.year + 99){ // eg: 4th century BC
- let ordinal = intToOrdinal(Math.abs(start.year - 1) / 100 + (start.year > 0 ? 1 : 0));
+ const ordinal = intToOrdinal(Math.abs(start.year - 1) / 100 + (start.year > 0 ? 1 : 0));
return ordinal + ' century' + (start.year < 0 ? ' BC' : '');
} else if (start.year % 10 == 0 && end.year == start.year + 9){ // eg: 1880s
return String(start.year) + 's';
} else {
- const suffixes = [' BC', ' AD'];
- for (let suffix of suffixes){ // eg: 1st Jan to 2nd Feb 100 AD
- if (startStr.endsWith(suffix) && endStr.endsWith(suffix)){
- return startStr.slice(0, startStr.length - suffix.length) + ' to ' + endStr;
- }
+ const bcRegex = /^(.*)( (BC|AD))$/;
+ const startMatch = bcRegex.exec(startStr);
+ const endMatch = bcRegex.exec(endStr);
+ if (startMatch != null && endMatch != null && startMatch[2] == endMatch[2]){
+ return `${startMatch[1]} to ${endStr}`;
}
}
} else if (start.gcal != null && end.gcal != null){
- const dateRegex = /^(\S*) (\S*) (.*)$/; // Matches day, month, and suffix
+ const dateRegex = /^(\S+) (\S+) (.*)$/; // Matches day, month, and suffix
const startMatch = dateRegex.exec(startStr);
const endMatch = dateRegex.exec(endStr);
if (startMatch != null && endMatch != null && startMatch[3] == endMatch[3]){ // Same suffix
@@ -354,6 +354,62 @@ export function boundedDateToStr(start: HistDate, end: HistDate | null) : string
}
return `${startStr} to ${endStr}`;
}
+export function eventDatesToStrings(
+ start: HistDate, startUpper: HistDate | null, end: HistDate | null, endUpper: HistDate | null)
+ : [string] | [string, string] {
+ if (end == null){
+ return [boundedDateToStr(start, startUpper)];
+ }
+ const startStr = boundedDateToStr(start, startUpper);
+ const endStr = boundedDateToStr(end, endUpper);
+ if (startStr == endStr){
+ return [startStr];
+ }
+ if (startStr.includes(' to ') || startStr.startsWith('About ')
+ || endStr.includes(' to ') || endStr.startsWith('About ')){
+ return [startStr, endStr];
+ }
+ let startMatch: null | string[];
+ let endMatch: null | string[];
+ if (start.gcal == null && end.gcal == null){
+ if (startStr.endsWith(' years ago') && endStr.endsWith(' years ago')){
+ const yaRegex = /^(.*) (.*) years ago$/;
+ startMatch = yaRegex.exec(startStr)!;
+ endMatch = yaRegex.exec(endStr)!;
+ if (startMatch[2] == endMatch[2]){ // Same billion/million/thousand scale
+ return [`${startMatch[1]} to ${endMatch[1]} ${startMatch[2]} years ago`];
+ } else {
+ return [`${startMatch[1]} ${startMatch[2]} to ${endMatch[1]} ${endMatch[2]} years ago`];
+ }
+ }
+ const mcRegex = /^(.*) (millenium|century( (BC|AD))?)$/;
+ startMatch = mcRegex.exec(startStr);
+ endMatch = mcRegex.exec(endStr);
+ if (startMatch != null && endMatch != null && startMatch[2] == endMatch[2]){
+ return [`${startMatch[1]} to ${endMatch[1]} ${startMatch[2]}`];
+ }
+ const bcRegex = /^(.*) (BC|AD)$/;
+ startMatch = bcRegex.exec(startStr);
+ endMatch = bcRegex.exec(endStr);
+ if (startMatch != null && endMatch != null && startMatch[2] == endMatch[2]){
+ return [`${startMatch[1]} to ${endStr}`];
+ }
+ } else if (start.gcal != null && end.gcal != null){
+ const calRegex = /^(\S+ )?(\S+) (.*)$/; // Matches day (optional), month, and suffix
+ startMatch = calRegex.exec(startStr);
+ endMatch = calRegex.exec(endStr);
+ if (startMatch != null && endMatch != null && startMatch[3] == endMatch[3]){ // Same suffix
+ if (startMatch[2] == endMatch[2]){ // Same month
+ return [`${startMatch[1]}to ${endMatch[1]}${startMatch[2]} ${startMatch[3]}`];
+ }
+ if (startMatch[1] == null){
+ return [`${startMatch[2]} to ${endMatch[2]} ${startMatch[3]}`];
+ }
+ return [`${startMatch[1]}${startMatch[2]} to ${endMatch[1]}${endMatch[2]} ${startMatch[3]}`];
+ }
+ }
+ return [startStr, endStr];
+}
// For event representation
export class HistEvent {
diff --git a/tests/lib.test.ts b/tests/lib.test.ts
index 36e729a..439703f 100644
--- a/tests/lib.test.ts
+++ b/tests/lib.test.ts
@@ -1,7 +1,7 @@
import {
moduloPositive, intToOrdinal, getNumTrailingZeros,
gregorianToJdn, julianToJdn, jdnToGregorian, jdnToJulian, gregorianToJulian, julianToGregorian, getDaysInMonth,
- YearDate, CalDate, boundedDateToStr, HistEvent,
+ YearDate, CalDate, boundedDateToStr, eventDatesToStr, HistEvent,
queryServer, jsonToHistDate, jsonToHistEvent,
DAY_SCALE, MONTH_SCALE, stepDate, inDateScale, getScaleRatio, getUnitDiff,
getEventPrecision, dateToUnit, dateToScaleDate,
@@ -91,45 +91,73 @@ describe('CalDate', () => {
})
})
test('toDisplayString', () => {
- expect(new YearDate(-14_000_000_000).toDisplayString()).equals('14 billion years ago')
- expect(new YearDate(-14_300_000_000).toDisplayString()).equals('14.3 billion years ago')
- expect(new YearDate( -1_230_000).toDisplayString()).equals('1.23 million years ago')
- expect(new YearDate( -1_234_567).toDisplayString()).equals('1.235 million years ago')
- expect(new YearDate( -123_456).toDisplayString()).equals('123 thousand years ago')
- expect(new YearDate( -9_999).toDisplayString()).equals('9,999 BC')
- expect(new YearDate( -200).toDisplayString()).equals('200 BC')
- expect(new YearDate( 1).toDisplayString()).equals('1 AD')
- expect(new YearDate( 1500).toDisplayString()).equals('1500')
- expect(new CalDate(2000, 10, 3).toDisplayString()).equals('3rd Oct 2000')
- expect(new CalDate(-2000, 1, 1).toDisplayString()).equals('1st Jan 2000 BC')
- expect(new CalDate(1610, 8, 6, false).toDisplayString()).equals('6th Aug 1610 (OS)')
- expect(new CalDate(-100, 2, 2, false).toDisplayString()).equals('2nd Feb 100 BC (OS)')
+ expect(new YearDate(-14_000_000_000).toDisplayString()).toBe('14 billion years ago')
+ expect(new YearDate(-14_300_000_000).toDisplayString()).toBe('14.3 billion years ago')
+ expect(new YearDate( -1_230_000).toDisplayString()).toBe('1.23 million years ago')
+ expect(new YearDate( -1_234_567).toDisplayString()).toBe('1.235 million years ago')
+ expect(new YearDate( -123_456).toDisplayString()).toBe('123 thousand years ago')
+ expect(new YearDate( -9_999).toDisplayString()).toBe('9,999 BC')
+ expect(new YearDate( -200).toDisplayString()).toBe('200 BC')
+ expect(new YearDate( 1).toDisplayString()).toBe('1 AD')
+ expect(new YearDate( 1500).toDisplayString()).toBe('1500')
+ expect(new CalDate(2000, 10, 3).toDisplayString()).toBe('3rd Oct 2000')
+ expect(new CalDate(-2000, 1, 1).toDisplayString()).toBe('1st Jan 2000 BC')
+ expect(new CalDate(1610, 8, 6, false).toDisplayString()).toBe('6th Aug 1610 (OS)')
+ expect(new CalDate(-100, 2, 2, false).toDisplayString()).toBe('2nd Feb 100 BC (OS)')
})
test('boundedDateToStr', () => {
// Start and end N billion/million/thousand years ago
- expect(boundedDateToStr(new YearDate(-1e9), new YearDate(-1e9))).equals('1 billion years ago')
- expect(boundedDateToStr(new YearDate(-2e9), new YearDate(-1.2e9))).equals('2 to 1.2 billion years ago')
- expect(boundedDateToStr(new YearDate(-2e6), new YearDate(-30e3))).equals('2 million to 30 thousand years ago')
- expect(boundedDateToStr(new YearDate(-2e6), new YearDate(-1e6 - 1))).equals('About 2 million years ago')
- expect(boundedDateToStr(new YearDate(-10_999), new YearDate(-10_000))).equals('About 11 thousand years ago')
+ expect(boundedDateToStr(new YearDate(-1e9), new YearDate(-1e9))).toBe('1 billion years ago')
+ expect(boundedDateToStr(new YearDate(-2e9), new YearDate(-1.2e9))).toBe('2 to 1.2 billion years ago')
+ expect(boundedDateToStr(new YearDate(-2e6), new YearDate(-30e3))).toBe('2 million to 30 thousand years ago')
+ expect(boundedDateToStr(new YearDate(-2e6), new YearDate(-1e6 - 1))).toBe('About 2 million years ago')
+ expect(boundedDateToStr(new YearDate(-10_999), new YearDate(-10_000))).toBe('About 11 thousand years ago')
// Other year-based start and end
- expect(boundedDateToStr(new YearDate(-2e6), new YearDate(100))).equals('2 million years ago to 100 AD')
- expect(boundedDateToStr(new YearDate(1), new YearDate(1000))).equals('1st millenium')
- expect(boundedDateToStr(new YearDate(1301), new YearDate(1400))).equals('14th century')
- expect(boundedDateToStr(new YearDate(-199), new YearDate(-100))).equals('2nd century BC')
- expect(boundedDateToStr(new YearDate(1880), new YearDate(1889))).equals('1880s')
- expect(boundedDateToStr(new YearDate(-100), new YearDate(-50))).equals('100 to 50 BC')
- expect(boundedDateToStr(new YearDate(310), new YearDate(1001))).equals('310 to 1001 AD')
- expect(boundedDateToStr(new YearDate(-10), new YearDate(2000))).equals('10 BC to 2000')
+ expect(boundedDateToStr(new YearDate(-2e6), new YearDate(100))).toBe('2 million years ago to 100 AD')
+ expect(boundedDateToStr(new YearDate(1), new YearDate(1000))).toBe('1st millenium')
+ expect(boundedDateToStr(new YearDate(1301), new YearDate(1400))).toBe('14th century')
+ expect(boundedDateToStr(new YearDate(-199), new YearDate(-100))).toBe('2nd century BC')
+ expect(boundedDateToStr(new YearDate(1880), new YearDate(1889))).toBe('1880s')
+ expect(boundedDateToStr(new YearDate(-100), new YearDate(-50))).toBe('100 to 50 BC')
+ expect(boundedDateToStr(new YearDate(310), new YearDate(1001))).toBe('310 to 1001 AD')
+ expect(boundedDateToStr(new YearDate(-10), new YearDate(2000))).toBe('10 BC to 2000')
// Calendar-based start and end
- expect(boundedDateToStr(new CalDate(100, 1, 2), new CalDate(101, 10, 3))).equals('2nd Jan 100 AD to 3rd Oct 101 AD')
- expect(boundedDateToStr(new CalDate(100, 1, 2), new CalDate(100, 10, 3))).equals('2nd Jan to 3rd Oct 100 AD')
- expect(boundedDateToStr(new CalDate(100, 1, 2), new CalDate(100, 1, 3))).equals('2nd to 3rd Jan 100 AD')
- expect(boundedDateToStr(new CalDate(100, 1, 1), new CalDate(100, 1, 31))).equals('Jan 100 AD')
- expect(boundedDateToStr(new CalDate(100, 1, 1, false), new CalDate(100, 1, 31, false))).equals('Jan 100 AD (OS)')
+ expect(boundedDateToStr(new CalDate(100, 1, 2), new CalDate(101, 10, 3))).toBe('2nd Jan 100 AD to 3rd Oct 101 AD')
+ expect(boundedDateToStr(new CalDate(100, 1, 2), new CalDate(100, 10, 3))).toBe('2nd Jan to 3rd Oct 100 AD')
+ expect(boundedDateToStr(new CalDate(100, 1, 2), new CalDate(100, 1, 3))).toBe('2nd to 3rd Jan 100 AD')
+ expect(boundedDateToStr(new CalDate(100, 1, 1), new CalDate(100, 1, 31))).toBe('Jan 100 AD')
+ expect(boundedDateToStr(new CalDate(100, 1, 1, false), new CalDate(100, 1, 31, false))).toBe('Jan 100 AD (OS)')
// Other
- expect(boundedDateToStr(new CalDate(10, 1, 2), null)).equals('2nd Jan 10 AD')
- expect(boundedDateToStr(new YearDate(-1e7), new CalDate(1610, 3, 2))).equals('10 million years ago to 2nd Mar 1610')
+ expect(boundedDateToStr(new CalDate(10, 1, 2), null)).toBe('2nd Jan 10 AD')
+ expect(boundedDateToStr(new YearDate(-1e7), new CalDate(1610, 3, 2))).toBe('10 million years ago to 2nd Mar 1610')
+})
+test('eventDatesToStr', () => {
+ // Year-based start and end
+ expect(eventDatesToStr(new YearDate(100), new YearDate(500), new YearDate(600)))
+ .toEqual(['100 to 500 AD', '600 AD'])
+ expect(eventDatesToStr(new YearDate(-2e6), new YearDate(-1e6 - 1), new YearDate(1)))
+ .toEqual(['About 2 million years ago', '1 AD'])
+ expect(eventDatesToStr(new YearDate(-3e9), null, new YearDate(-1e9), null))
+ .toBe('3 to 1 billion years ago')
+ expect(eventDatesToStr(new YearDate(-5e6), new YearDate(-5e6), new YearDate(-2.2e6), null))
+ .toEqual('5 to 2.2 million years ago')
+ expect(eventDatesToStr(new YearDate(1), new YearDate(1000), new YearDate(2001), new YearDate(3000)))
+ .toEqual('1st to 3rd millenium')
+ expect(eventDatesToStr(new YearDate(-1099), new YearDate(-1000), new YearDate(-499), new YearDate(-400)))
+ .toEqual('11th to 5th century BC')
+ expect(eventDatesToStr(new YearDate(13), null, new YearDate(300), new YearDate(300)))
+ .toEqual('13 to 300 AD')
+ // Calendar-based start and end
+ expect(eventDatesToStr(new CalDate(1, 1, 1), null, new CalDate(1, 3, 2), null))
+ .toEqual('1st Jan to 2nd Mar 1 AD')
+ expect(eventDatesToStr(new CalDate(1, 1, 1), null, new CalDate(1, 1, 2), null))
+ .toEqual('1st to 2nd Jan 1 AD')
+ expect(eventDatesToStr(new CalDate(1670, 9, 1), new CalDate(1670, 9, 30),
+ new CalDate(1670, 10, 1), new CalDate(1670, 10, 31)))
+ .toEqual('Sep to Oct 1670')
+ // Other
+ expect(eventDatesToStr(new CalDate(10, 1, 2), null, null, null)).toBe('2nd Jan 10 AD')
+ expect(eventDatesToStr(new YearDate(1000), null, new YearDate(1000), null)).toBe('1000 AD')
})
test('queryServer', async () => {