D3 Time Format
d3-time-format is a core D3 module providing robust JavaScript utilities for formatting and parsing dates and times, inspired by the venerable `strftime` and `strptime` functions from the C standard library. Currently stable at version 4.1.0, this package typically releases new major versions for significant breaking changes or feature additions, while minor and patch releases address bug fixes and smaller enhancements. It enables developers to convert `Date` objects into human-readable, locale-specific strings and vice-versa, making it indispensable for data visualization and applications requiring precise time representation. A key differentiator is its deep integration within the D3 ecosystem, frequently used alongside D3 time scales, and its comprehensive support for various format specifiers and internationalization through locale definitions, which were notably enhanced in recent versions like 4.1.0 with additional exports and updates. It explicitly adopted modern JavaScript features like `type: module` in v4 and ES2015 in v3, signaling a commitment to contemporary development practices.
Common errors
-
ReferenceError: require is not defined
cause Attempting to use CommonJS `require()` syntax to import d3-time-format in an ES Module context or with d3-time-format v4+.fixChange `const { timeFormat } = require('d3-time-format');` to `import { timeFormat } from 'd3-time-format';`. -
SyntaxError: Cannot use import statement outside a module
cause Attempting to use ES Module `import` syntax in a CommonJS context without proper configuration, especially with d3-time-format v4+.fixEnsure your project's `package.json` has `"type": "module"` if you intend to use ESM, or configure your bundler (Webpack, Rollup) to handle ESM. Alternatively, use dynamic `import()` for CJS-only environments if absolutely necessary for a v4+ package. -
Invalid Date
cause A `Date` object returned by `timeParse` is 'Invalid Date' because the input string did not match the provided specifier, or a custom locale was not loaded.fixDouble-check that the format `specifier` precisely matches the input date string. Ensure all necessary locale definitions are loaded if parsing a locale-specific string.
Warnings
- breaking Version 4.0.0 adopted `type: module`, making it an ES Module (ESM) exclusively. It also raised the minimum Node.js requirement to v12 or higher. Projects using CommonJS (CJS) `require()` syntax will break.
- breaking Version 3.0.0 adopted ES2015 language features (e.g., `for-of`), dropping support for older browsers like Internet Explorer. Environments that do not support ES2015 will encounter runtime errors.
- gotcha Loading locale definitions (e.g., for `timeFormatDefaultLocale`) requires a network request (e.g., `d3.json`) and is asynchronous. Forgetting to wait for the locale to load before using formatters can lead to incorrect or default locale output.
- gotcha The `timeFormat` and `timeParse` functions operate on local time by default, potentially leading to unexpected results if UTC handling is expected. `utcFormat` and `utcParse` should be used explicitly for UTC-based operations.
Install
-
npm install d3-time-format -
yarn add d3-time-format -
pnpm add d3-time-format
Imports
- timeFormat
const timeFormat = require('d3-time-format').timeFormat;import { timeFormat } from 'd3-time-format'; - timeParse
import timeParse from 'd3-time-format/timeParse';
import { timeParse } from 'd3-time-format'; - utcFormat
import { utcFormat } from 'd3-time-format'; - timeFormatDefaultLocale
d3.timeFormatDefaultLocale = locale;
import { timeFormatDefaultLocale } from 'd3-time-format';
Quickstart
import { timeFormat } from 'd3-time-format';
import { timeSecond, timeMinute, timeHour, timeDay, timeWeek, timeMonth, timeYear } from 'd3-time';
// This quickstart demonstrates how to use d3-time-format to create a
// multi-scale time formatter, which dynamically changes the date
// format based on the time interval being displayed. This pattern is
// commonly used in D3 visualizations for axis labels or tooltips
// to provide appropriate granularity.
const formatMillisecond = timeFormat(".%L");
const formatSecond = timeFormat(":%S");
const formatMinute = timeFormat("%I:%M");
const formatHour = timeFormat("%I %p");
const formatDay = timeFormat("%a %d");
const formatWeek = timeFormat("%b %d");
const formatMonth = timeFormat("%B");
const formatYear = timeFormat("%Y");
function multiFormat(date: Date): string {
return (timeSecond(date) < date ? formatMillisecond
: timeMinute(date) < date ? formatSecond
: timeHour(date) < date ? formatMinute
: timeDay(date) < date ? formatHour
: timeMonth(date) < date ? (timeWeek(date) < date ? formatDay : formatWeek)
: timeYear(date) < date ? formatMonth
: formatYear)(date);
}
// Example usage with various dates to show different formats
const now = new Date();
const dateInMs = new Date(now.getTime() - 500); // Less than a second ago
const dateInSeconds = new Date(now.getTime() - 15 * 1000); // 15 seconds ago
const dateInMinutes = new Date(now.getTime() - 5 * 60 * 1000); // 5 minutes ago
const dateInHours = new Date(now.getTime() - 3 * 60 * 60 * 1000); // 3 hours ago
const dateInDays = new Date(now.getTime() - 2 * 24 * 60 * 60 * 1000); // 2 days ago
const dateInWeeks = new Date(now.getTime() - 3 * 7 * 24 * 60 * 60 * 1000); // 3 weeks ago
const dateInMonths = new Date(now.getTime() - 2 * 30 * 24 * 60 * 60 * 1000); // 2 months ago
const dateInYears = new Date(now.getTime() - 1 * 365 * 24 * 60 * 60 * 1000); // 1 year ago
console.log(`Millisecond format: ${multiFormat(dateInMs)}`);
console.log(`Second format: ${multiFormat(dateInSeconds)}`);
console.log(`Minute format: ${multiFormat(dateInMinutes)}`);
console.log(`Hour format: ${multiFormat(dateInHours)}`);
console.log(`Day format: ${multiFormat(dateInDays)}`);
console.log(`Week format: ${multiFormat(dateInWeeks)}`);
console.log(`Month format: ${multiFormat(dateInMonths)}`);
console.log(`Year format: ${multiFormat(dateInYears)}`);