Skip to content

Commit

Permalink
Date fixes (#448)
Browse files Browse the repository at this point in the history
* Implement validation & date display in editor

* Update tests

* Refactor

* Update date calculations & tests
  • Loading branch information
khoidt authored Feb 23, 2024
1 parent 61b7a1b commit 8149b4b
Show file tree
Hide file tree
Showing 10 changed files with 122 additions and 76 deletions.
2 changes: 1 addition & 1 deletion src/chronology/application/DateConverterFormChange.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ it('handles setToGregorianDate scenario correctly', () => {
setFormData: mockSetFormData,
setScenario,
})
expect(mockDateConverter.setToGregorianDate).toBeCalledWith(-309, 3, 29)
expect(mockDateConverter.setToGregorianDate).toBeCalledWith(-310, 3, 29)
})

it('handles setToJulianDate scenario correctly', () => {
Expand Down
64 changes: 56 additions & 8 deletions src/chronology/application/DateSelection.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
} from 'chronology/ui/DateEditor/DateSelectionInput'
import useDateSelectionState, {
DateEditorStateProps,
DateSelectionState,
} from 'chronology/application/DateSelectionState'

type Props = {
Expand All @@ -30,6 +31,28 @@ interface DateEditorProps extends DateEditorStateProps {
isDisplayed: boolean
}

function getSelectedDateAndValidation(
state: DateSelectionState,
savedDate?: MesopotamianDate
): { selectedDate?: MesopotamianDate; isSelectedDateValid: boolean } {
let isSelectedDateValid: boolean
let selectedDate: MesopotamianDate | undefined
try {
selectedDate = state.getDate()
const dateString = selectedDate.toString()
const isDatesNotSame =
savedDate === undefined || dateString !== savedDate.toString()
const isDateEmpty = dateString.replaceAll('SE', '') !== ''
const isAssyrianDateNotEmpty =
!state.isAssyrianDate || dateString !== '∅.∅.1'
isSelectedDateValid =
isDateEmpty && isAssyrianDateNotEmpty && isDatesNotSame
} catch {
isSelectedDateValid = false
}
return { selectedDate, isSelectedDateValid }
}

export function DateEditor({
date,
setDate,
Expand All @@ -55,27 +78,50 @@ export function DateEditor({
const dateOptionsInput = DateOptionsInput({ ...state })
const dateInputGroups = DateInputGroups({ ...state })

const saveButton = (
const deleteButton = (
<Button
className="m-1"
variant="danger"
disabled={false}
onClick={() => state.saveDate(state.getDate(), index)}
onClick={() => state.saveDate(undefined, index)}
>
Save
Delete
</Button>
)

const deleteButton = (
const { selectedDate, isSelectedDateValid } = getSelectedDateAndValidation(
state,
date
)

const saveButton = (
<Button
className="m-1"
variant="danger"
disabled={false}
onClick={() => state.saveDate(undefined, index)}
disabled={!isSelectedDateValid}
onClick={() => state.saveDate(state.getDate(), index)}
>
Delete
Save
</Button>
)

const savedDateDisplay = date ? (
<>
<b>Saved date</b>
<DateDisplay date={date} />
</>
) : (
''
)
const selectedDateDisplay =
selectedDate && isSelectedDateValid ? (
<>
<b>Selected date</b>
<DateDisplay date={selectedDate} />
</>
) : (
''
)

const popover = (
<Popover
style={{ maxWidth: '600px' }}
Expand All @@ -85,6 +131,8 @@ export function DateEditor({
<Popover.Content>
{dateOptionsInput}
{dateInputGroups}
{savedDateDisplay}
{selectedDateDisplay}
{date && deleteButton}
{saveButton}
<Spinner loading={isSaving}>Saving...</Spinner>
Expand Down
14 changes: 7 additions & 7 deletions src/chronology/domain/Date.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ describe('MesopotamianDate', () => {
true
)
expect(date.toString()).toBe(
'12.V.10 SE (30 August 302 BCE PJC | 25 August 301 BCE PGC)'
'12.V.10 SE (30 August 302 BCE PJC | 25 August 302 BCE PGC)'
)
})

Expand All @@ -123,7 +123,7 @@ describe('MesopotamianDate', () => {
true
)
expect(date.toString()).toBe(
'∅.V.10 SE (ca. 19 August 302 BCE PJC | ca. 14 August 301 BCE PGC)'
'∅.V.10 SE (ca. 19 August 302 BCE PJC | ca. 14 August 302 BCE PGC)'
)
})

Expand All @@ -137,7 +137,7 @@ describe('MesopotamianDate', () => {
true
)
expect(date.toString()).toBe(
'12.∅.10 SE (ca. 4 May 302 BCE PJC | ca. 29 April 301 BCE PGC)'
'12.∅.10 SE (ca. 4 May 302 BCE PJC | ca. 29 April 302 BCE PGC)'
)
})

Expand All @@ -164,7 +164,7 @@ describe('MesopotamianDate', () => {
false
)
expect(date.toString()).toBe(
'12.V.10 Darius I (11 August 512 BCE PJC | 5 August 511 BCE PGC)'
'12.V.10 Darius I (11 August 512 BCE PJC | 5 August 512 BCE PGC)'
)
})

Expand All @@ -179,7 +179,7 @@ describe('MesopotamianDate', () => {
false
)
expect(date.toString()).toBe(
'∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 511 BCE PGC)'
'∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)'
)
})

Expand All @@ -194,7 +194,7 @@ describe('MesopotamianDate', () => {
false
)
expect(date.toString()).toBe(
'12.∅.10 Darius I (ca. 16 April 512 BCE PJC | ca. 10 April 511 BCE PGC)'
'12.∅.10 Darius I (ca. 16 April 512 BCE PJC | ca. 10 April 512 BCE PGC)'
)
})

Expand All @@ -209,7 +209,7 @@ describe('MesopotamianDate', () => {
false
)
expect(date.toString()).toBe(
'∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 511 BCE PGC)'
'∅.V.10 Darius I (ca. 31 July 512 BCE PJC | ca. 25 July 512 BCE PGC)'
)
})

Expand Down
35 changes: 11 additions & 24 deletions src/chronology/domain/DateBase.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,23 +95,19 @@ export class MesopotamianDateBase {
}

toModernDate(calendar: 'Julian' | 'Gregorian' = 'Julian'): string {
const { year, month, day, isApproximate } = this.getDateApproximation()
const dateProps = {
year,
month,
day,
isApproximate,
...this.getDateApproximation(),
calendar,
}
let julianDate = ''
if (this.isSeleucidEraApplicable(year)) {
if (this.isSeleucidEraApplicable(dateProps.year)) {
julianDate = this.seleucidToModernDate(dateProps)
} else if (this.isNabonassarEraApplicable()) {
julianDate = this.getNabonassarEraDate(dateProps)
} else if (this.isAssyrianDateApplicable()) {
julianDate = this.getAssyrianDate({ calendar: 'Julian' })
} else if (this.isKingDateApplicable()) {
julianDate = this.kingToModernDate({ year, calendar: 'Julian' })
julianDate = this.kingToModernDate({ ...dateProps, calendar: 'Julian' })
}
return julianDate
}
Expand Down Expand Up @@ -144,24 +140,14 @@ export class MesopotamianDateBase {
day: number
isApproximate: boolean
} {
let year = parseInt(this.year.value)
let month = parseInt(this.month.value)
let day = parseInt(this.day.value)
const isApproximate = this.isApproximate()
if (isNaN(month)) {
month = 1
}
if (isNaN(day)) {
day = 1
}
if (isNaN(year)) {
year = -1
}
const year = parseInt(this.year.value)
const month = parseInt(this.month.value)
const day = parseInt(this.day.value)
return {
year,
month,
day,
isApproximate: isApproximate,
year: isNaN(year) ? -1 : year,
month: isNaN(month) ? 1 : month,
day: isNaN(day) ? 1 : day,
isApproximate: this.isApproximate(),
}
}

Expand Down Expand Up @@ -221,6 +207,7 @@ export class MesopotamianDateBase {
}
return ''
}

private kingToModernDate({
year,
calendar = 'Julian',
Expand Down
29 changes: 14 additions & 15 deletions src/chronology/domain/DateConverter.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import DateConverter from 'chronology/domain/DateConverter'
const dateJulianEraBegin = {
bcJulianYear: 311,
cjdn: 1607923,
gregorianYear: -309,
bcGregorianYear: 310,
gregorianYear: -310,
bcGregorianYear: 311,
gregorianMonth: 3,
gregorianDay: 29,
julianDay: 3,
Expand All @@ -23,8 +23,8 @@ const dateJulianEraBegin = {
}

const dateNebuchadnezzarIIY43M12D28 = {
gregorianYear: -559,
bcGregorianYear: 560,
gregorianYear: -560,
bcGregorianYear: 561,
gregorianMonth: 3,
gregorianDay: 28,
julianYear: -560,
Expand All @@ -44,8 +44,8 @@ const dateNebuchadnezzarIIY43M12D28 = {
}

const dateNebuchadnezzarIIY23M10D14 = {
gregorianYear: -580,
bcGregorianYear: 581,
gregorianYear: -581,
bcGregorianYear: 582,
gregorianMonth: 12,
gregorianDay: 28,
julianYear: -580,
Expand All @@ -65,8 +65,8 @@ const dateNebuchadnezzarIIY23M10D14 = {
}

const dateSeleucidY100M12D26 = {
gregorianYear: -209,
bcGregorianYear: 210,
gregorianYear: -210,
bcGregorianYear: 211,
gregorianMonth: 3,
gregorianDay: 30,
julianYear: -210,
Expand All @@ -89,25 +89,24 @@ const dateSeleucidY100M12D26 = {

describe('DateConverter', () => {
let mesopotamianDate: DateConverter

beforeEach(() => {
mesopotamianDate = new DateConverter()
})

test('Check initial state', () => {
const expected = dateJulianEraBegin
expect(mesopotamianDate.calendar).toEqual(expected)
expect(mesopotamianDate.toDateString()).toEqual('29 March 310 BCE PGC')
expect(mesopotamianDate.toDateString()).toEqual('29 March 311 BCE PGC')
expect(mesopotamianDate.toDateString('Julian')).toEqual(
'3 April 311 BCE PJC'
)
})

test('Set to Gregorian date', () => {
const expected = dateNebuchadnezzarIIY43M12D28
mesopotamianDate.setToGregorianDate(-559, 3, 28)
mesopotamianDate.setToGregorianDate(-560, 3, 28)
expect(mesopotamianDate.calendar).toEqual(expected)
expect(mesopotamianDate.toDateString()).toEqual('28 March 560 BCE PGC')
expect(mesopotamianDate.toDateString()).toEqual('28 March 561 BCE PGC')
expect(mesopotamianDate.toDateString('Julian')).toEqual(
'3 April 561 BCE PJC'
)
Expand All @@ -117,7 +116,7 @@ describe('DateConverter', () => {
const expected = dateNebuchadnezzarIIY43M12D28
mesopotamianDate.setToJulianDate(-560, 4, 3)
expect(mesopotamianDate.calendar).toEqual(expected)
expect(mesopotamianDate.toDateString()).toEqual('28 March 560 BCE PGC')
expect(mesopotamianDate.toDateString()).toEqual('28 March 561 BCE PGC')
expect(mesopotamianDate.toDateString('Julian')).toEqual(
'3 April 561 BCE PJC'
)
Expand All @@ -127,7 +126,7 @@ describe('DateConverter', () => {
const expected = dateNebuchadnezzarIIY23M10D14
mesopotamianDate.setToMesopotamianDate('Nebuchadnezzar II', 23, 10, 14)
expect(mesopotamianDate.calendar).toEqual(expected)
expect(mesopotamianDate.toDateString()).toEqual('28 December 581 BCE PGC')
expect(mesopotamianDate.toDateString()).toEqual('28 December 582 BCE PGC')
expect(mesopotamianDate.toDateString('Julian')).toEqual(
'3 January 581 BCE PJC'
)
Expand All @@ -137,7 +136,7 @@ describe('DateConverter', () => {
mesopotamianDate.setToSeBabylonianDate(100, 12, 26)
const expected = dateSeleucidY100M12D26
expect(mesopotamianDate.calendar).toEqual(expected)
expect(mesopotamianDate.toDateString()).toEqual('30 March 210 BCE PGC')
expect(mesopotamianDate.toDateString()).toEqual('30 March 211 BCE PGC')
expect(mesopotamianDate.toDateString('Julian')).toEqual(
'3 April 211 BCE PJC'
)
Expand Down
26 changes: 12 additions & 14 deletions src/chronology/domain/DateConverterCompute.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ export default class DateConverterCompute {
)
const { quotient: alpha2b, remainder: m0 } = divmod(m1 + 2, 12)
return {
year: a1 + alpha2b < 1 ? a1 + alpha2b + 1 : a1 + alpha2b,
year: a1 + alpha2b < 1 ? a1 + alpha2b : a1 + alpha2b,
month: m0 + 1,
day: Math.floor(epsilon1 / 5) + 1,
}
Expand Down Expand Up @@ -111,19 +111,17 @@ export default class DateConverterCompute {
gregorianMonth: number
gregorianDay: number
}): number {
gregorianYear = gregorianYear < 1 ? gregorianYear - 1 : gregorianYear
const alpha1 = Math.floor((gregorianMonth - 3) / 12)
const m1 = (gregorianMonth - 3) % 12
const a1 = gregorianYear + alpha1
return (
365 * a1 +
Math.floor(a1 / 4) -
Math.floor(a1 / 100) +
Math.floor(a1 / 400) +
Math.floor((153 * m1 + 2) / 5) +
gregorianDay +
1721119
)
if (gregorianMonth < 3) {
gregorianYear -= 1
gregorianMonth += 12
}
gregorianYear = gregorianYear === 0 ? -1 : gregorianYear
const monthDays = Math.floor(30.6001 * (gregorianMonth + 1))
const century = Math.floor(gregorianYear / 100)
const leapYearCorrection = Math.floor(century / 4)
const fixedDay = 2 - century + leapYearCorrection
const yearDays = Math.floor(365.25 * (gregorianYear + 4716))
return Math.floor(fixedDay + gregorianDay + yearDays + monthDays - 1524)
}

computeWeekDay(cjdn: number): number {
Expand Down
Loading

0 comments on commit 8149b4b

Please sign in to comment.