Dates andDmy

Work with timezone-free calendar values across ordinary dates, BCE history, deep time, and millisecond-level timelines.

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.

JavaScript
// 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.
  • T or 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.

JavaScript
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'
);
Defaults belong to the 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.

JavaScript
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.

TokenOutput
YYYYYear, with BCE text when required
MMMThree-letter English month name
DDay of month
HHZero-padded hour
mmZero-padded minute
ssZero-padded second
SSSThree-digit millisecond
JavaScript
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

Arithmetic

Move a calendar value by whole days or a duration expressed in hours through milliseconds.

MethodResult
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).
JavaScript
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

Comparison

Compare calendar positions or measure the difference between them.

MethodReturns
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.
JavaScript
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.

JavaScript
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.

JavaScript
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 a Dmy whose year is NaN for invalid grammar and retains legacy field normalization. Prefer strings as Timeline DateValue inputs, 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(), and getPreviousMonth() 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() and Dmy.getByDayOfYear() expose ordinal-day calculations.
  • getDaysSinceYearZero(), getLeapYearsSinceYearZero(), getMillisecondsOfDay(), and toKeyString() expose low-level values used by library calculations and keys.
  • Dmy.CreateAsStartOfPeriod(), Dmy.CreateAsEndOfPeriod(), and Dmy.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.