diff --git a/src/App.tsx b/src/App.tsx index a2c3557..32beb94 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,7 +1,7 @@ import React from 'react'; import './App.css'; import {Calendar} from './Calendar'; -import {gregorianJDN, Month} from "./dates"; +import {gregorianJDN, jdnFrench, Month} from "./dates"; type YearMonth = { year: number; @@ -28,12 +28,13 @@ class App extends React.Component<{}, AppState> { constructor(props: {}) { super(props); - const current = {year: 230, month: 5}; const today = new Date(); + const todayJDN = gregorianJDN(today.getFullYear(), today.getMonth() + 1, today.getDay()); + const {year, month} = jdnFrench(todayJDN); this.state = { - ...(parseURL() || current as YearMonth), - todayJDN: gregorianJDN(today.getFullYear(), today.getMonth() + 1, today.getDay()), + ...(parseURL() || {year, month}), + todayJDN, }; this.updateURL(); this.updateStateFromURL = this.updateStateFromURL.bind(this); diff --git a/src/dates.test.ts b/src/dates.test.ts index d11b515..c517f70 100644 --- a/src/dates.test.ts +++ b/src/dates.test.ts @@ -1,4 +1,4 @@ -import {dateName, frJDN, gregorianJDN, jdnGregorian, jdnLongCount, monthName} from './dates'; +import {dateName, frJDN, gregorianJDN, jdnFrench, jdnGregorian, jdnLongCount, monthName} from './dates'; describe('gregorianJDN', () => { it('works', () => { @@ -30,6 +30,22 @@ describe('frJDN', () => { }); }); +describe('jdnFrench', () => { + it('works for sample dates', () => { + expect(jdnFrench(2375840)).toEqual({year: 1, month: 1, day: 1}); + expect(jdnFrench(2378444)).toEqual({year: 8, month: 2, day: 18}); + }); + + it('works in years starting/ending near midnight', () => { + expect(jdnFrench(2416017)).toEqual({year: 111, month: 1, day: 1}); + expect(jdnFrench(2450715)).toEqual({year: 206, month: 1, day: 1}); + expect(jdnFrench(3284926)).toEqual({year: 2490, month: 1, day: 1}); + expect(jdnFrench(2416016)).toEqual({year: 110, month: 13, day: 6}); + expect(jdnFrench(2450714)).toEqual({year: 205, month: 13, day: 6}); + expect(jdnFrench(3284925)).toEqual({year: 2489, month: 13, day: 5}); + }); +}); + describe('jdnGregorian', () => { it('works', () => { expect(jdnGregorian(0)).toEqual(new Date(-4713, 10, 24)); diff --git a/src/dates.ts b/src/dates.ts index 7c6a6f9..260cbec 100644 --- a/src/dates.ts +++ b/src/dates.ts @@ -34,10 +34,10 @@ export type Day = | 29 | 30; -export type GregorianDate = { +export type FrenchDate = { year: number, - month: number, - day: number, + month: Month, + day: Day, }; const monthNames: { @@ -96,6 +96,26 @@ export function jdnGregorian(jdn: number): Date { return new Date(year, month - 1, day); } +export function jdnFrench(jdn: number): FrenchDate { + let lo = 0; + let hi = leaps.length; + + while (lo + 1 < hi) { + const mid = Math.floor((lo + hi) / 2); + if (startJD + 365 * mid + leaps[mid] <= jdn) + lo = mid; + else + hi = mid; + } + + const dd = jdn - (startJD + 365 * lo + leaps[lo]); + return { + year: startYear + lo, + month: Math.floor(dd / 30) + 1 as Month, + day: dd % 30 + 1 as Day, + } +} + export function jdnLongCount(jdn: number): string | null { let z = jdn - 584283; if (z < 0)