Resources Numerical accuracy Calculation policy

4D schedule dates and status

Reads task dates from a schedule file and says, for a date, which elements are built, in progress or not started.

How the precision is kept

Dates are whole day numbers since 1970-01-01 (UTC), so every comparison is between integers. A day that does not exist (2026-02-30) is refused.

Calculations under this policy

3 calculations in 1 source file. The code is read from the released app when this page loads. It is the calculation people run, not a copy kept for this page.

ifc-4d.js BimCraft 0.8.1 Exact 3 calculations Reviewed

Tests tools/bimcraft-test/schedule-test.mjs, bin/test-bimcraft.mjs

Date text as a day number

Exact

A YYYY-MM-DD date as a count of days since 1970-01-01.

day = Date.UTC(y, m, d) ÷ 86400000

Midnight UTC is a whole multiple of 86,400,000 ms, so the quotient is an integer; Math.round changes nothing. The date is built back and compared to refuse days that do not exist.

  • ifc-4d.js
  • lines 36 to 43
  • BimCraft 0.8.1
export function parseDay(s) {
  const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(String(s ?? '').trim());
  if (!m) return null;
  const d = Date.UTC(+m[1], +m[2] - 1, +m[3]);
  const back = new Date(d);
  if (back.getUTCFullYear() !== +m[1] || back.getUTCMonth() !== +m[2] - 1 || back.getUTCDate() !== +m[3]) return null;   // 2026-02-30
  return Math.round(d / 86400000);
}

Built, in progress or waiting on a date

Exact

The state of every element that belongs to a task, on a chosen day.

built if day > finish; in progress if start ≤ day ≤ finish; waiting if day < start

Integer comparisons of day numbers. An element in several tasks is built only when every task is, and in progress when some are built and others not started.

  • ifc-4d.js
  • lines 127 to 136
  • BimCraft 0.8.1
export function statusAt(matched, day) {
  const all = new Map();   // key → [built, progress, waiting] counts over its tasks
  for (const t of matched) {
    const i = day > t.finish ? 0 : day >= t.start ? 1 : 2;   // in progress from Start through Finish, built the day after
    for (const k of t.keys) { let c = all.get(k); if (!c) all.set(k, (c = [0, 0, 0])); c[i]++; }
  }
  const st = new Map();
  for (const [k, c] of all) st.set(k, c[1] || (c[0] && c[2]) ? 'progress' : c[0] ? 'built' : 'waiting');   // built in one task, not started in another: still being worked on
  return st;
}

Task counts of a stage or package

Exact

How many tasks of a group are done, running and still to do on a day.

Integer comparisons and counts.

  • ifc-4d.js
  • lines 185 to 189
  • BimCraft 0.8.1
export function groupState(tasks, day) {
  const n = { done: 0, now: 0, todo: 0 };
  for (const t of tasks) n[day > t.finish ? 'done' : day >= t.start ? 'now' : 'todo']++;
  return n;
}

In detail

Method
day = milliseconds at 00:00 UTC ÷ 86,400,000. A task is in progress from its start day through its finish day and built from the day after.
Number types
Integers held in 64-bit numbers.
Limits
Dates only: no time of day and no time zones.

Approach: Exact values

Constants and factors are held as exact fractions from their definitions. The arithmetic is ordered so that no rounded factor is ever used.

Every policy that takes this approach