Public
Edited
Jul 29, 2024
Paused
Comments locked
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
fullYear = yearOfEra + era * 400 + (month <= 2)
Insert cell
month = mp + (mp < 10 ? 3 : -9) // map our internal month number to the civil month number
Insert cell
dayOfMonth = dayOfYear - div(offset * mp + 2, 5) + 1
Insert cell
diff = datediff(void 0, 0)
Insert cell
z === div(diff, 1000 * meanSolarDay) // expected output: true
Insert cell
z === daysFromCivil(fullYear, month, dayOfMonth) // expected output: true
Insert cell
civilFromDays(z)
Insert cell
Insert cell
mp = div(5 * dayOfYear + 2, offset) // mp === 0 is March, mp === 11 is February
Insert cell
/*!
* A value of:
* - 0 corresponds to March 1
* - 364 corresponds to February 28 of the following (civil) year
*/
dayOfYear = dayOfEra -
(365 * yearOfEra + div(yearOfEra, 4) - div(yearOfEra, 100))
Insert cell
yearOfEra = div(
dayOfEra -
div(dayOfEra, daysPer["4Y"]) +
div(dayOfEra, daysPer["100Y"]) -
div(dayOfEra, daysPer["400Y"]),
365
)
Insert cell
dayOfEra = Z - era * (daysPer["400Y"] + 1)
Insert cell
era = div(Z >= 0 ? Z : Z - daysPer["400Y"], (daysPer["400Y"] + 1))
Insert cell
Z = z + shift // shift the epoch from 1970-01-01 to 0000-03-01
Insert cell
Insert cell
z = div(+new Date(), 1000 * meanSolarDay) // today
Insert cell
Insert cell
Insert cell
origin = ((record) => (record && record["start date"]) || "0000-03-01")(
data.filter((d) => d.era === 0)[0]
)
Insert cell
shift = div(datediff(0, origin), 1000 * meanSolarDay)
Insert cell
Insert cell
Insert cell
Insert cell
/**
* Returns (year, month, day) triple in civil calendar
*
* @typedef {Object} Triple
* @property {number} year - full year
* @property {number} month - month [1, 12]
* @property {number} day - day of month
*
* @param {number} z - number of days since 1970-01-01
* @return {Triple} (year, month, day) triple
*/
function civilFromDays(z) {
/* thank you, Howard Hinnant! - mg */
z += shift;
const e = div(z >= 0 ? z : z - daysPer["400Y"], daysPer["400Y"] + 1);
const doe = z - e * (daysPer["400Y"] + 1); // [0, 146096]
const yoe = div(
doe -
div(doe, daysPer["4Y"]) +
div(doe, daysPer["100Y"]) -
div(doe, daysPer["400Y"]),
365
); // [0, 399]
const doy = doe - (365 * yoe + div(yoe, 4) - div(yoe, 100)); // [0, 365]
const mp = div(5 * doy + 2, offset); // [0, 11]
const day = doy - div(offset * mp + 2, 5) + 1; // [1, 31]
const month = mp < 10 ? mp + 3 : mp - 9; // [1, 12]
const year = yoe + e * 400 + (month <= 2);
return { year, month, day };
}
Insert cell
/**
* Returns the number of days since civil 1970-01-01.
* Negative values indicate days prior to 1970-01-01.
*
* (year, month, day) represents a date in the civil (Gregorian) calendar
*
* @param {number} year - full year
* @param {number} month - month [1, 12]
* @param {number} day - day of month
* @return {number} number of days since 1970-01-01
*/
function daysFromCivil(year, month, day) {
/* thank you, Howard Hinnant! - mg */
year -= month <= 2;
const e = div(year >= 0 ? year : year - 399, 400);
const yoe = year - e * 400; // [0, 399]
const doy =
div(offset * (month > 2 ? month - 3 : month + 9) + 2, 5) +
day -
1; // [0, 365]
const doe = yoe * 365 + div(yoe, 4) - div(yoe, 100) + doy; // [0, 146096]
return e * (daysPer["400Y"] + 1) + doe - shift;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
div = (a, n) => ((r) => (a - r) / n)(mod(a, n))
Insert cell
mod = (a, n) => (a % n) + (sign(a) !== sign(n) ? n : 0)
Insert cell
sign = Math.sign ||
((n) => {
if (n == 0 || isNaN(n)) {
return +n;
}
return n < 0 ? -1 : 1;
})
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more