[Note / no action required] What it would take to move away from MATLAB datenums for timebases/timestamps
Nobody has claimed this yet.
- Dominant language
- MATLAB
- Stars
- 1
- Forks
- 2
- Avg merge
- 2h 18m
- Merged PRs (30d)
- 39
Description
This is an informational design note, not a bug or a scheduled task. It records, for future reference, every place MATLAB datenum is currently baked into the DID/NDI/NDR stack and what a coordinated migration would involve, so the decision can be made deliberately later. No resolution is required; the current datenum-based behavior is intentional and backward-compatible. Decision (2026-06): keep datenum for now.
Context: came out of reviewing DID-matlab #146 (the SQL-literal escaping fix), which deliberately defers the timestamp-format question (audit §6.1-2 / §7.3-13, see docs/Audit_Remediation_Results_2026-06-12.md). #146 itself changes no serialization and is backward-compatible; this note is the separate, larger "what if we ever change the time representation" picture.
Where datenum lives today
There are several distinct uses of datenum — they are independent and have very different blast radii. The two that actually represent timebases stored in data are #2 (DID SQL column) and #4–#6 (NDI/NDR global epoch times).
DID-matlab
did.idoidentifiers —did.ido.unique_idbuilds IDs as[num2hex(serial_date_number) '_' num2hex(rand)], i.e. a datenum is embedded in every persistent document/branch ID. These are opaque primary keys, not a timebase. Their datenum derivation is internal and never read back as a time. Changing it would invalidate every stored ID for no benefit — explicitly out of scope for any timebase migration.- SQL bookkeeping
timestampcolumn (docs/branches/branch_docs, declaredtimestamp NUMERIC) — written insrc/did/+did/+implementations/sqlitedb.m(do_add_branch, add-doc, add-to-branch) as MATLABnow= datenum-days. DID-python writestime.time()= Unix epoch-seconds into the same column, so cross-client comparisons already diverge. Note: in DID-matlab this column is currently write-only — nothingSELECTs, sorts, or compares it — so within MATLAB the practical blast radius is low today. - DID document
timestamp-typed fields (schema typetimestamp, validated insrc/did/+did/database.mviajava.time.LocalDateTime.parse) — already ISO-8601 text, cross-language safe. No change needed; this is the model to follow.
NDI-matlab
- Global epoch timebases (
exp_global_time/utc) are persisted as datenum-days in thet0_t1of eachepoch_clockentry inside epoch/element documents.- Consumer:
src/ndi/+ndi/+fun/+docTable/epoch.mreads the global-clock index withdatetime(..., 'convertFrom','datenum'). - Producers also include the import converters, e.g.
+ndi/+setup/+conv/+haley/doImport.m(convertTo(datetime(...)+seconds(t0_t1_local),'datenum')) and+ndi/+setup/+conv/+babu/import.m. - (Device-local
t0_t1, e.g. the Intan reader, is just seconds-from-zero — not affected.)
- Consumer:
ndi.cacheentrytimestampusesnow(src/ndi/+ndi/cache.m) — in-memory only, not persisted; low concern.
NDR-matlab
- The ABF reader is the root producer of the persisted global datenum timebase. In
+ndr/+reader/axon_abf.m,get_t0_t1_from_headerbuilds the global clock ast0t1{2} = [datenum(dt) datenum(dt+seconds(t1))]from the file'suFileStartDate, andepochclockadvertisesexp_global_timeonly whenuFileStartDateis present. ABF is special because the file carries an absolute wall-clock start; most other readers only return device-local seconds.
Flow: ABF uFileStartDate → axon_abf emits exp_global_time t0_t1 as datenum → bridged via +ndi/+daq/+reader/+mfdaq/ndr.m → persisted in epoch documents' epoch_clock/t0_t1 → read back by ndi.fun.docTable.epoch with convertFrom datenum.
What a migration would require (if ever undertaken)
This is a cross-repo, cross-client change — doing it on one side alone would break the others and any already-stored data.
- Pick a target representation, jointly for DID-matlab, DID-python, NDI-matlab, NDR-matlab, and the cloud backend. Candidates: Unix epoch-seconds (double or int64), int64 nanoseconds, or ISO-8601 TEXT (as DID already uses for
timestamp-typed fields). - Version the format so old vs new data is distinguishable — a
class_version/schema bump for documents and a format flag/migration marker for the SQL column — rather than silently reinterpreting existing numbers. - One-time migration of existing stored rows (SQL
timestampcolumn) and existing documents (NDI globalt0_t1). - Update producers and consumers in lockstep:
- DID SQL writers in
sqlitedb.m(+ DID-python equivalents) for thetimestampcolumn. - NDR
axon_abf.get_t0_t1_from_header/epochclock. - NDI import converters (
+setup/+conv/...) and thendi.fun.docTable.epochreader, plus any analysis code that consumes globalt0_t1.
- DID SQL writers in
- Leave
did.idoIDs alone (item #1) — out of scope.
Precision note (already understood)
datenum-days stored as a double gives only ~10 µs resolution near year 2026 (the integer day count consumes most of the mantissa) — within, but close to, the 0.1 ms spec for utc/exp_global_time in ndi.time.clocktype. Epoch-seconds (double) would give sub-µs; int64 ns would be exact. This is a motivation to keep in mind, not an urgent problem.
Summary
- DID-matlab #146 is backward-compatible and does not depend on any of this.
- The current
datenumbehavior is intentional; this note exists only so a future change can be made with full knowledge of the touch-points across DID, NDI, and NDR. - No action required.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
This is an informational design note with no implementation requested. For any future work, start by reading src/did/+did/+implementations/sqlitedb.m, +ndr/+reader/axon_abf.m, and src/ndi/+ndi/+fun/+docTable/epoch.m, then trace the listed import converters. Done would require an agreed cross-repository representation, versioning, migration, and coordinated producer/consumer updates.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- matlab, python, sqlite
- Domain
- backend, databases, documentation
- Issue type
- Documentation
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Needs clarification
- Newbie friendliness
- 15/100