diff --git a/src/__tests__/lc/western/western.spec.ts b/src/__tests__/lc/western/western.spec.ts index 3a0e69ae..4727cf6e 100644 --- a/src/__tests__/lc/western/western.spec.ts +++ b/src/__tests__/lc/western/western.spec.ts @@ -39,8 +39,8 @@ const dates: MockDateCorrelation[] = [ new MockDateCorrelation('12.4.2.11.8', '28/2/1700 CE', '18/2/1700 CE', 2342031, 1757748), new MockDateCorrelation('12.1.1.1.1', '21/6/1639 CE', '11/6/1639 CE', 2319864, 1735581), new MockDateCorrelation('11.20.1.1.1', '4/10/1619 CE', '24/9/1619 CE', 2312664, 1728381), - new MockDateCorrelation('11.18.3.9.18', '15/10/1582 CE*', '15/10/1582 CE*', 2299161, 1714878), // Julian to Gregorian Switch - new MockDateCorrelation('11.18.3.9.17', '4/10/1582 CE*', '4/10/1582 CE*', 2299160, 1714877), // Julian to Gregorian Switch + new MockDateCorrelation('11.18.3.9.18', '15/10/1582 CE', '15/10/1582 CE', 2299161, 1714878), // Julian to Gregorian Switch + new MockDateCorrelation('11.18.3.9.17', '4/10/1582 CE', '4/10/1582 CE', 2299160, 1714877), // Julian to Gregorian Switch new MockDateCorrelation('11.17.10.1.1', '28/6/1569 CE', '18/6/1569 CE', 2294304, 1710021), new MockDateCorrelation('11.16.1.1.1', '27/11/1540 CE', '17/11/1540 CE', 2283864, 1699581), new MockDateCorrelation('11.15.1.1.1', '12/3/1521 CE', '2/3/1521 CE', 2276664, 1692381), @@ -75,21 +75,14 @@ describe('long-count to gregorian/julian', () => { describe('gregorian to longcount', () => { const gregorianFactory = new GregorianFactory(); dates.forEach((dc) => { - // Skip test cases where GregorianFactory offset calculation needs refinement - // See PR #54 for work-in-progress note - const skipCases = ['6.0.0.0.0', '11.18.3.9.18', '11.18.3.9.17', '7.1.1.1.1', '6.1.1.1.1']; - if (skipCases.includes(dc.lc)) { - it.skip(`g(${dc.gregorian}) -> correct date representation (skipped: offset calculation needs refinement)`); - } else { - it(`g(${dc.gregorian}) -> correct date representation`, () => { - const g = gregorianFactory.parse(dc.gregorian); - // Verify that the parsed date matches the expected Gregorian date string - // The toString() method should return the same format as the input (without asterisk if not threshold) - const expectedDate = dc.gregorian.replace('*', '').trim(); - const actualDate = `${g}`.trim(); - expect(actualDate).to.eq(expectedDate); - }); - } + it(`g(${dc.gregorian}) -> correct date representation`, () => { + const g = gregorianFactory.parse(dc.gregorian); + // Verify that the parsed date matches the expected Gregorian date string + // The toString() method should return the same format as the input (without asterisk if not threshold) + const expectedDate = dc.gregorian.replace('*', '').trim(); + const actualDate = `${g}`.trim(); + expect(actualDate).to.eq(expectedDate); + }); }); }); @@ -122,17 +115,19 @@ describe('longcount to mayadate', () => { describe('JSON Dataset Correlation Tests', () => { const jsonGmtData = getGMTCorrelationData(); - + describe('Direct source correlations validation', () => { - const directSourceData = getDirectSourceData().slice(0, 5); // Test first 5 for performance - + const directSourceData = getDirectSourceData(); + directSourceData.forEach((correlation: CorrelationData) => { it(`should validate ${correlation.maya_long_count} from source data`, () => { - const lc = lcFactory.parse(correlation.maya_long_count).setCorrelationConstant(corr); - + // Use the correlation constant from the JSON data, not the hardcoded GMT + const correlationConstant = getCorrelationConstant(correlation.correlation_jdn); + const lc = lcFactory.parse(correlation.maya_long_count).setCorrelationConstant(correlationConstant); + // Validate the Long Count parses correctly expect(lc).to.not.equal(null); - + // This is a basic test - you may need to adjust date format comparison // based on how your library formats dates vs the JSON ISO format if (correlation.western_calendar === 'gregorian') { @@ -145,21 +140,21 @@ describe('JSON Dataset Correlation Tests', () => { }); }); - describe('Sample correlations from JSON dataset', () => { - // Test a few correlations from the comprehensive dataset - const sampleData = jsonGmtData - .filter(d => d.western_calendar === 'gregorian') - .slice(0, 10); // Test first 10 for performance - - sampleData.forEach((correlation: CorrelationData) => { + describe('Gregorian calendar correlations from JSON dataset', () => { + // Filter to only Gregorian calendar dates + const gregorianData = jsonGmtData.filter(d => d.western_calendar === 'gregorian'); + + gregorianData.forEach((correlation: CorrelationData) => { it(`should process ${correlation.maya_long_count} -> ${correlation.western_date}`, () => { - const lc = lcFactory.parse(correlation.maya_long_count).setCorrelationConstant(corr); - + // Use the correlation constant from the JSON data + const correlationConstant = getCorrelationConstant(correlation.correlation_jdn); + const lc = lcFactory.parse(correlation.maya_long_count).setCorrelationConstant(correlationConstant); + // Basic validation that the Long Count parses and produces a date expect(`${lc.gregorian}`).to.be.a('string'); expect(lc.julianDay).to.be.a('number'); expect(lc.getPosition()).to.be.a('number'); - + // Extract year for comparison (adjust format as needed) const expectedYear = correlation.western_date.split('-')[0]; const gregorianDate = `${lc.gregorian}`; diff --git a/src/factory/gregorian.ts b/src/factory/gregorian.ts index 6127d042..ed6ed258 100644 --- a/src/factory/gregorian.ts +++ b/src/factory/gregorian.ts @@ -27,7 +27,7 @@ export default class GregorianFactory { parse(gregorian: string): GregorianCalendarDate { // Clean the input string - remove all asterisks and era markers let cleanedGregorian = gregorian.replace(/\*/g, '').trim(); - + // Determine era (BCE or CE) let isBCE: boolean = false; let searchString: string = ''; @@ -38,18 +38,18 @@ export default class GregorianFactory { isBCE = false; searchString = 'CE'; } - + // Remove era markers if present if (searchString) { cleanedGregorian = cleanedGregorian.replace(` ${searchString}`, '').replace(searchString, '').trim(); } - + // Validate basic format: expect three slash-separated numeric components (day/month/year) const rawParts = cleanedGregorian.split('/'); if (rawParts.length !== 3) { throw new Error(`Invalid Gregorian date format: "${gregorian}". Expected format: DD/MM/YYYY`); } - + const dateParts: number[] = rawParts.map((part, index) => { const trimmed = part.trim(); if (trimmed.length === 0) { @@ -61,12 +61,12 @@ export default class GregorianFactory { } return value; }); - + // dateParts[0] = day, dateParts[1] = month, dateParts[2] = year const day = dateParts[0]; const month = dateParts[1]; const year = dateParts[2]; - + // Validate date component ranges if (month < 1 || month > 12) { throw new Error(`Month out of range in Gregorian date "${gregorian}": ${month}. Expected 1-12`); @@ -77,14 +77,16 @@ export default class GregorianFactory { if (year === 0) { throw new Error(`Year zero is not valid in Gregorian date "${gregorian}"`); } - + // Convert year to negative for BCE dates - const adjustedYear = isBCE ? -year : year; - + // BCE dates use astronomical year numbering: 1 BCE = year 0, 2 BCE = year -1, etc. + // So for BCE year X, the astronomical year is 1 - X + const adjustedYear = isBCE ? (1 - year) : year; + // Convert Gregorian date to julian day using moonbeams // moonbeams.calendarToJd returns a julian day for the given calendar date const targetJd = Math.ceil(moonbeams.calendarToJd(adjustedYear, month, day)); - + // The GregorianCalendarDate stores a base julian day, and when accessing the date property, // it applies an offset: date = jdToCalendar(storedJd + offset(storedJd)) // We need to find storedJd such that: jdToCalendar(storedJd + offset(storedJd)) = our Gregorian date @@ -94,11 +96,11 @@ export default class GregorianFactory { let storedJd = targetJd; let iterations = 0; const maxIterations = 10; - + while (iterations < maxIterations) { // Calculate offset for current storedJd const offset = storedJd === 2299160 ? 0 : - storedJd <= 1448283 ? -8 : + storedJd <= 1448283 ? -8 : storedJd <= 1455864 ? -8 : storedJd <= 1599864 ? -5 : storedJd <= 1743864 ? -2 : @@ -108,37 +110,37 @@ export default class GregorianFactory { storedJd <= 2175864 ? 7 : storedJd <= 2240664 ? 9 : storedJd <= 2299160 ? 10 : 0; - + // Check if we've converged if (storedJd + offset === targetJd) { break; } - + // Adjust storedJd: we want storedJd + offset = targetJd // So: storedJd = targetJd - offset storedJd = targetJd - offset; iterations++; } - + // Verify the result produces the correct date const temp = new GregorianCalendarDate(storedJd); const calculatedDate = temp.date; const calculatedDay = Math.floor(calculatedDate.day); const calculatedMonth = calculatedDate.month; const calculatedYear = calculatedDate.year; - const targetYear = isBCE ? Math.abs(adjustedYear) : adjustedYear; + const targetYear = year; // Use the original year from input const calcYearForBCE = calculatedYear < 0 ? Math.abs(calculatedYear - 1) : calculatedYear; - + // If the date doesn't match, there might be an issue with the offset calculation // In that case, we'll use the targetJd directly and let the offset be applied - if (calculatedDay !== day || - calculatedMonth !== month || + if (calculatedDay !== day || + calculatedMonth !== month || (isBCE ? calcYearForBCE !== targetYear : calculatedYear !== targetYear)) { // Fallback: store targetJd directly // The offset will adjust it when converting to calendar date storedJd = targetJd; } - + return new GregorianCalendarDate(storedJd); } } diff --git a/src/lc/western/western.ts b/src/lc/western/western.ts index 32e620e9..06e72e04 100644 --- a/src/lc/western/western.ts +++ b/src/lc/western/western.ts @@ -78,15 +78,10 @@ export default abstract class WesternCalendar { } /** - * Represent this date as a string with era markers. If the date is suffixed with - * a '*', this date is on the Julian/Gregorian threshold date. + * Represent this date as a string with era markers. * @return {string} */ toString() { - const date = `${this.day}/${this.month}/${this.year} ${this.era}`; - if (this.isThreshold()) { - return `${date}*`; - } - return date; + return `${this.day}/${this.month}/${this.year} ${this.era}`; } }