Dates and Dmy
HistropediaJS uses timezone-free calendar values throughout its timeline APIs. This section covers the supported date input formats and the built-in Dmy helper for constructing, formatting, comparing, and performing arithmetic on dates.
Calendar Values and DateValue Inputs
HistropediaJS dates represent positions in the proleptic Gregorian calendar, not JavaScript Date
instants. They do not contain a timezone and are not converted to or from UTC. This allows the same date
representation to work consistently for historical, BCE, and deep-time dates without depending on the viewer's
locale or timezone.
Timeline navigation, initial position, viewport bounds, and other date-based APIs accept a DateValue
in any of three forms: a date/time parts object, a Dmy instance, or a canonical Histropedia date
string.
// Date/time parts object
timeline.setStartDate({
year: 2026,
month: 8,
day: 13,
hour: 12,
minute: 30
});
// Constructed Dmy value
timeline.setCentreDate(new Histropedia.Dmy(2026, 8, 13, 12, 30));
// Canonical Histropedia date string
timeline.setCentreDate('2026-08-13T12:30');
The canonical string grammar is:
year[-month[-day]][T| ]hour[:minute[:second[.SSS]]]
- The complete time portion is optional.
- Years may be negative or contain more than four digits.
- Fractional seconds contain one to three digits and are right-padded to milliseconds.
Tor a space may separate the date and time.- Timezone suffixes such as
Z, UTC offsets, named timezones, and longer fractions are rejected by timeline APIs.
The grammar check validates the string's structure, not every supplied field as a strict calendar validator. Supply valid calendar and time components rather than relying on legacy normalization.
timeline.setStartDate('2026-08-13T12:30:15.25'); // Fractional seconds become .250
timeline.setCentreDate('-44-03-15 09:01');
timeline.fitDateRange(
'1000000000-06-15T12:00:00.000',
'1000000000-06-15T12:00:00.010'
);
DateValue layer.
Timeline APIs default an omitted month or day to 1 and omitted time fields to 0.
The raw Dmy constructor does not default an omitted month or day. For
fitDateRange(), a time-free year-only or month-only string represents the complete period; a
time-bearing string represents an exact calendar position.
Construct Dmy Values
Dmy is included in both module and script-tag builds. Import it by name when using npm or an ES
module, or access it through the global Histropedia object in a UMD build.
new Dmy(...)
Calendar value
Create a mutable Histropedia calendar value from positional fields or an object.
Signatures
new Dmy(year, month, day, hour?, minute?, second?, millisecond?)
Use fully specified year, month, and day values. Optional time fields default to zero.
new Dmy({ year, month, day, hour?, minute?, second?, millisecond?, precision? })
The object form retains an explicit precision value or infers sub-day precision from its finest supplied time component.
Returns
Dmy – A calendar value whose public fields remain writable for backwards compatibility.
import { Dmy } from 'histropediajs';
const exact = new Dmy(2026, 8, 13, 12, 30, 15, 250);
const articleDate = new Dmy({
year: 1969,
month: 7,
day: 20,
hour: 20,
minute: 17
});
articleDate.precision; // 'minute' — inferred from the supplied minute
// With a script-tag build, use the same constructor from the global:
const globalDate = new Histropedia.Dmy(1969, 7, 20);
Supply valid calendar and time components: month 1–12, hour 0–23, minute
and second 0–59, and millisecond 0–999. Dmy preserves legacy
normalization behaviour, but it is not intended to be a strict input validator.
Although fields are writable, examples should treat each Dmy as a value. Prefer the arithmetic
methods below, which return another instance, instead of directly changing fields in application code.
Format Dates and Deep Time
.format(format?, options?)
Formatting
Format the calendar fields using Histropedia's compact date tokens.
Parameters
format string
Optional token string. Defaults to 'D MMM YYYY'.
options DmyFormatOptions
Optional yearPrefix, bceText, and thousandsSeparator settings.
| Token | Output |
|---|---|
YYYY | Year, with BCE text when required |
MMM | Three-letter English month name |
D | Day of month |
HH | Zero-padded hour |
mm | Zero-padded minute |
ss | Zero-padded second |
SSS | Three-digit millisecond |
const exact = new Histropedia.Dmy(2026, 8, 13, 12, 30, 15, 250);
exact.format('D MMM YYYY HH:mm:ss.SSS');
// '13 Aug 2026 12:30:15.250'
const deepTime = new Histropedia.Dmy(1200000000, 1, 1);
deepTime.format('YYYY', {
yearPrefix: { value: 1000000000, label: ' Ga' }
});
// '1.2 Ga'
const bce = new Histropedia.Dmy(0, 3, 15);
bce.format('D MMM YYYY', { bceText: ' BCE' });
// '15 Mar 1 BCE'
thousandsSeparator changes digit grouping in full year output. When yearPrefix is
applied, the result contains the scaled year and its label rather than the rest of the format string.
Safe Day and Time Arithmetic
The day and time arithmetic methods return a new Dmy; they do not change the original. They cross
month, year, leap-day, and BCE/CE boundaries, and retain precision resolved through object-form construction.
Day and time methods
ArithmeticMove a calendar value by whole days or a duration expressed in hours through milliseconds.
| Method | Result |
|---|---|
addDays(amount) | Moves by a whole number of calendar days; fractional amounts are truncated. |
addHours(amount) | Moves by the supplied number of hours. |
addMinutes(amount) | Moves by the supplied number of minutes. |
addSeconds(amount) | Moves by the supplied number of seconds. |
addMilliseconds(amount) | Moves by the supplied number of milliseconds. |
getNextDay() | Equivalent to addDays(1). |
getPreviousDay() | Equivalent to addDays(-1). |
const start = new Histropedia.Dmy({
year: 2026,
month: 8,
day: 13,
hour: 12,
minute: 30,
second: 15,
millisecond: 250,
precision: 'millisecond'
});
const later = start.addHours(1).addMinutes(15);
later.format('D MMM YYYY HH:mm:ss.SSS');
// '13 Aug 2026 13:45:15.250'
start.format('HH:mm'); // '12:30' — unchanged
later.precision; // 'millisecond' — retained
Compare and Measure Dates
Comparison and difference methods
ComparisonCompare calendar positions or measure the difference between them.
| Method | Returns |
|---|---|
isSame(other) | true when all calendar and time fields represent the same position. |
isAfter(other) | true when this value is later than other. |
isBetween(from, to) | true only when this value is strictly between the two endpoints. |
compare(other) | -1, 0, or 1 for before, equal, or after. |
getDaysTo(other) | Calendar-day difference, including a fractional day for time components. |
getMonthsTo(other) | Approximate decimal month difference. |
getYearsTo(other) | Approximate decimal year difference. |
isInFuture() | Whether this value is later than the current local date and time. |
const from = new Histropedia.Dmy(2026, 8, 13, 12, 0);
const candidate = new Histropedia.Dmy(2026, 8, 13, 12, 30);
const to = new Histropedia.Dmy(2026, 8, 13, 13, 0);
candidate.isBetween(from, to); // true
from.isBetween(from, to); // false: endpoints are excluded
candidate.compare(to); // -1
from.getDaysTo(to); // 1 / 24
BCE Numbering
Dmy uses astronomical-style internal numbering. Internal year 1 is 1 CE, year
0 is 1 BCE, and year -1 is 2 BCE. Dmy.format() converts that numbering
into a historical BCE label.
Timeline input is controlled by shiftBceDates.
With its default value of false, negative input years are used directly. Set it to
true when application data uses -1 to mean 1 BCE; HistropediaJS then adds one to
negative input years during timeline normalization. This happens before article and time-band precision
boundaries are resolved.
const internalOneBce = new Histropedia.Dmy(0, 1, 1);
internalOneBce.format('YYYY', { bceText: ' BCE' }); // '1 BCE'
const timeline = new Histropedia.Timeline(container, {
shiftBceDates: true
});
timeline.setCentreDate({ year: -1, month: 1, day: 1 });
// The input convention treats -1 as 1 BCE.
Precision Metadata
Precision describes the granularity of a date used by article, time-band, or chart data. It is metadata rather than a timezone or formatting setting: articles and time bands use it to resolve a calendar range, while chart points use the normalized start of the selected precision.
Supported strings are 'millisecond', 'second', 'minute',
'hour', 'day', 'month', 'year', 'decade',
'century', 'millennium', 'million-years', and
'billion-years'. When precision is omitted from a date-parts object, the finest supplied time key
determines it: millisecond, then second, minute, or hour.
A value of 0 still counts as supplied. Date-only objects continue to default to 'day',
including objects containing only a year or a year and month. Explicit precision always overrides inference;
existing falsy precision values retain the day fallback.
Object-form Dmy construction applies the same inference and retains the resolved precision. The
recommended day/time arithmetic methods carry it to the returned value. Positional Dmy construction
does not infer precision. Precision does not itself change how arithmetic or formatting methods behave.
const minuteValue = new Histropedia.Dmy({
year: 1969,
month: 7,
day: 20,
hour: 20,
minute: 17
});
minuteValue.precision; // 'minute' — inferred
const nextMinute = minuteValue.addMinutes(1);
nextMinute.precision; // 'minute'
const wholeDay = new Histropedia.Dmy({
year: 1969,
month: 7,
day: 20,
hour: 20,
precision: 'day' // Explicit precision overrides inference
});
timeline.load([{
id: 'moon-landing',
title: 'Apollo 11 Moon landing',
from: minuteValue
}]);
See the Article precision reference for complete start/end boundary rules, and try the Date Precision example to compare the resolved ranges interactively.
Legacy and Low-level Helpers
The public type declarations include additional compatibility and engine-oriented methods. They are listed here so existing code can identify their contracts, but they are not recommended as the starting point for new date workflows:
Dmy.fromString()returns aDmywhose year isNaNfor invalid grammar and retains legacy field normalization. Prefer strings as TimelineDateValueinputs, where invalid grammar throws an error.Dmy.now()returns the current local calendar date at midnight, not the current time.addMonths()supports its legacy positive-amount use case and returns the first day of the resulting month; negative amounts do not perform conventional subtraction.addYears(),getNextMonth(), andgetPreviousMonth()return the first day of their resulting year or month.asFloat()returns an approximate decimal-year value rounded to two places and cannot preserve sub-day precision.convertToIso()adjusts negative BCE numbering by mutating and returning the same instance.getDayOfYear()andDmy.getByDayOfYear()expose ordinal-day calculations.getDaysSinceYearZero(),getLeapYearsSinceYearZero(),getMillisecondsOfDay(), andtoKeyString()expose low-level values used by library calculations and keys.Dmy.CreateAsStartOfPeriod(),Dmy.CreateAsEndOfPeriod(), andDmy.CreateAsExclusiveEndOfPeriod()are the precision-boundary factories used by the data model.
Need More Help?
If you can't find what you're looking for, browse the examples or contact us.