mirror of
https://github.com/quantum5/qcal.git
synced 2025-04-24 09:41:57 -04:00
Implement handling of complementary days
This commit is contained in:
parent
2c3657248b
commit
dc435b7870
|
@ -64,6 +64,24 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@include media-breakpoint-up(lg) {
|
||||||
|
.ComplementaryDays {
|
||||||
|
@include make-row();
|
||||||
|
|
||||||
|
> * {
|
||||||
|
@include make-col-ready();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.ComplementaryDay {
|
||||||
|
@include make-col($columns: 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ComplementaryDays-splitter {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.Day, .DecadeName {
|
.Day, .DecadeName {
|
||||||
margin: 0.5em;
|
margin: 0.5em;
|
||||||
@include make-col($columns: 10);
|
@include make-col($columns: 10);
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Calendar.scss';
|
import './Calendar.scss';
|
||||||
import {Day, decadeNames, frJDN, jdnGregorian, jdnLongCount, Month, monthName} from './dates';
|
import {dateName, Day, decadeNames, frIsLeap, frJDN, jdnGregorian, jdnLongCount, Month, monthName} from './dates';
|
||||||
|
|
||||||
type MonthProps = {
|
type MonthProps = {
|
||||||
year: number;
|
year: number;
|
||||||
|
@ -53,9 +53,26 @@ function NormalMonth({year, month, todayJDN}: MonthProps & { todayJDN: number })
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function ComplementaryDay({year, month, day, todayJDN}: DateProps & { todayJDN: number }): JSX.Element {
|
||||||
|
const jdn = frJDN(year, month, day);
|
||||||
|
return <div className={`Day ComplementaryDay ${jdn === todayJDN ? 'Day-today' : ''}`}>
|
||||||
|
<div className="Day-name">{dateName(month, day)}</div>
|
||||||
|
<DayDetail jdn={jdn}/>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
|
||||||
|
function ComplementaryDays({year, todayJDN}: {year: number, todayJDN: number}): JSX.Element {
|
||||||
|
return <div className="ComplementaryDays">{
|
||||||
|
Array.from(Array(frIsLeap(year) ? 6 : 5).keys()).map(i => <>
|
||||||
|
<ComplementaryDay year={year} month={13} day={i + 1 as Day} todayJDN={todayJDN}/>
|
||||||
|
{i % 2 === 1 && <div className="ComplementaryDays-splitter"/>}
|
||||||
|
</>)
|
||||||
|
}</div>;
|
||||||
|
}
|
||||||
|
|
||||||
export class Calendar extends React.Component<CalendarProps, CalendarState> {
|
export class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||||
private goToNormalized(year: number, month: number) {
|
private goToNormalized(year: number, month: number) {
|
||||||
if (month < 0) {
|
if (month < 1) {
|
||||||
--year;
|
--year;
|
||||||
month += 13;
|
month += 13;
|
||||||
}
|
}
|
||||||
|
@ -95,7 +112,9 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||||
onClick={this.prevMonth.bind(this)}>‹
|
onClick={this.prevMonth.bind(this)}>‹
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div className="Calendar-month-name">{monthName(this.props.month)} {this.props.year}</div>
|
<div className="Calendar-month-name">
|
||||||
|
{this.props.month < 13 && monthName(this.props.month)} {this.props.year}
|
||||||
|
</div>
|
||||||
<div className="Calendar-next">
|
<div className="Calendar-next">
|
||||||
<button type="button" className="btn btn-secondary" title="Next month"
|
<button type="button" className="btn btn-secondary" title="Next month"
|
||||||
onClick={this.nextMonth.bind(this)}>›
|
onClick={this.nextMonth.bind(this)}>›
|
||||||
|
@ -105,7 +124,8 @@ export class Calendar extends React.Component<CalendarProps, CalendarState> {
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<NormalMonth year={this.props.year} month={this.props.month} todayJDN={this.props.todayJDN}/>
|
{this.props.month < 13 && <NormalMonth year={this.props.year} month={this.props.month} todayJDN={this.props.todayJDN}/>}
|
||||||
|
{this.props.month === 13 && <ComplementaryDays year={this.props.year} todayJDN={this.props.todayJDN}/>}
|
||||||
</div>;
|
</div>;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import {dateName, frJDN, gregorianJDN, jdnFrench, jdnGregorian, jdnLongCount, monthName} from './dates';
|
import {dateName, frIsLeap, frJDN, gregorianJDN, jdnFrench, jdnGregorian, jdnLongCount, monthName} from './dates';
|
||||||
|
|
||||||
describe('gregorianJDN', () => {
|
describe('gregorianJDN', () => {
|
||||||
it('works', () => {
|
it('works', () => {
|
||||||
|
@ -30,6 +30,25 @@ describe('frJDN', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('frIsLeap', () => {
|
||||||
|
it('works for sample dates', () => {
|
||||||
|
expect(frIsLeap(1)).toBeFalsy();
|
||||||
|
expect(frIsLeap(8)).toBeFalsy();
|
||||||
|
expect(frIsLeap(3)).toBeTruthy();
|
||||||
|
expect(frIsLeap(7)).toBeTruthy();
|
||||||
|
expect(frIsLeap(11)).toBeTruthy();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('works in years starting/ending near midnight', () => {
|
||||||
|
expect(frIsLeap(110)).toBeTruthy();
|
||||||
|
expect(frIsLeap(205)).toBeTruthy();
|
||||||
|
expect(frIsLeap(2489)).toBeFalsy();
|
||||||
|
expect(frIsLeap(111)).toBeFalsy();
|
||||||
|
expect(frIsLeap(206)).toBeFalsy();
|
||||||
|
expect(frIsLeap(2490)).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe('jdnFrench', () => {
|
describe('jdnFrench', () => {
|
||||||
it('works for sample dates', () => {
|
it('works for sample dates', () => {
|
||||||
expect(jdnFrench(2375840)).toEqual({year: 1, month: 1, day: 1});
|
expect(jdnFrench(2375840)).toEqual({year: 1, month: 1, day: 1});
|
||||||
|
|
|
@ -87,6 +87,10 @@ export function frJDN(year: number, month: Month, day: Day): number {
|
||||||
return startJD + 365 * dy + leaps[dy] + dd;
|
return startJD + 365 * dy + leaps[dy] + dd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function frIsLeap(year: number): boolean {
|
||||||
|
return !!data.leap[year - startYear];
|
||||||
|
}
|
||||||
|
|
||||||
export function jdnGregorian(jdn: number): Date {
|
export function jdnGregorian(jdn: number): Date {
|
||||||
const e = 4 * (jdn + 1401 + Math.floor(Math.floor((4 * jdn + 274277) / 146097) * 3 / 4) - 38) + 3;
|
const e = 4 * (jdn + 1401 + Math.floor(Math.floor((4 * jdn + 274277) / 146097) * 3 / 4) - 38) + 3;
|
||||||
const h = 5 * Math.floor((e % 1461 + 1461) % 1461 / 4) + 2;
|
const h = 5 * Math.floor((e % 1461 + 1461) % 1461 / 4) + 2;
|
||||||
|
|
Loading…
Reference in a new issue