Skip to content

πŸ“œ Version 3.x History ​

[v3.10.0] - 2026-07-19 ​

✨ What's New ​

Format Token Modifiers & Custom Tokens Introduced new capabilities for chained formatting modifiers and finalized the complete architecture for Custom Format Tokens. Developers can now register custom zero-overhead logic evaluators (like Fiscal Years or native Intl bridges) that seamlessly hook into the t.format() engine.

πŸ“š Documentation Enhancements ​

  • Cookbook Refactoring: Trimmed architectural "bloat" from the Cookbook (including Localized Parsing, Slick Mutations, and Custom Tokens). This content has been moved into dedicated Core Concepts guides (tempo.parse.md, tempo.mutate.md, tempo.format.md) to provide a much punchier, fast-paced onboarding experience for new users, while keeping deep-dive details just one click away.

[v3.9.0] - 2026-07-14 ​

✨ What's New ​

Historical Era Support Introduced first-class support for historical dates. The new {era} formatting token automatically resolves to localized BC/AD or BCE/CE designations. Additionally, the core Tempo class now exposes .era and .eon zero-cost getters, providing immediate access to the underlying historical date components.

Typographical Auto-Meridiem Expanded the {h12} token modifiers with a new :space option. When chaining modifiers (like {h12:space:dots}), Tempo will now gracefully inject a readability space before the auto-appended meridiem, yielding typographically correct strings like "10:30 a.m." instead of "10:30a.m.".

πŸ“š Documentation Enhancements ​

  • Educational Guides: Created a brand new tempo.getters.md document in the Core Concepts section, serving as the definitive guide to Tempo's zero-cost lazy-evaluation properties.
  • Ecosystem Alignment: Updated tempo.config.md to remove deprecated plugin references, replacing them with accurate examples from the current tempo-workspace (FinanceNamespace and AstroTerm).

πŸͺ² Bug Fixes & Stability ​

  • Core Typings: Resolved any leakage in Tempo core methods by injecting strict overloads for until() and since() directly into tempo.class.ts, ensuring full IDE type-inference flows through to .format().
  • Documentation Badges: Standardized the Shields.io badge layout across the monorepo to use <p> tags with inline-block styling, fixing horizontal alignment issues caused by VitePress CSS overrides and eliminating malformed HTML <table> hydration errors.
  • Vue Compiler Hydration: Fixed a rogue unclosed </p> tag in the Ticker plugin documentation that was silently causing downstream Vue SFC parsing errors during VitePress compilation.
  • CLI Pipeline: Validated the magma-cli build pipeline to correctly propagate non-zero exit codes during workspace orchestration operations, preventing silent failures.

[v3.8.0] - 2026-07-11 ​

✨ What's New ​

Interval Primitive Introduced Interval as a first-class, tree-shakeable core primitive. It provides mathematically pure, high-performance boundary evaluations (overlaps, abuts, contains) and set operations (union, intersection) for Temporal points. Interval is accessible ergonomically via Tempo.Interval or independently as a named export for strict tree-shaking purists.

Namespace Architecture Introduced the defineNamespace plugin factory. While Terms (like quarter or season) teach Tempo how to parse natural language, Namespaces provide a clean way to attach grouped business logic directly to the Tempo instance without polluting the global scope. For example, t.finance.isFiscalYearStart() or t.finance.taxYear keeps financial computations neatly isolated from standard date mechanics.

πŸ—οΈ Internal Refactoring ​

  • Strict Plugin Discrimination: The plugin registry now enforces strict 'type' discrimination ('plugin' | 'namespace' | 'term' | 'module') across all plugin factories, replacing brittle object-sniffing and making introspection significantly more robust.
  • Documentation Architecture: The documentation source code has been completely reorganized into numbered sub-directories (1-getting-started, 2-core-concepts, etc.) to map 1:1 with the visual VitePress sidebar.

[v3.7.1] - 2026-07-09 ​

πŸͺ² Bug Fix ​

  • License Admin Isolation: Improved license handling so administrative access is tracked separately, reducing incorrect license/permission information appearing in the app.
  • Admin Cache Protection: Prevented outdated role information from lingering after license updates.

[v3.7.0] - 2026-07-08 ​

✨ What's New β€” Runtime Version Registry ​

Tempo now features a fully automated runtime version registry accessible via Tempo.versions. This allows developers to instantly query exactly which core modules, terms, and community plugins are loaded into their current Tempo environment and what versions they are running. This system is completely zero-burden for plugin authors, utilizing a virtual build pipeline to auto-inject version strings without requiring manual updates or magic strings.

πŸ—οΈ Internal Refactoring ​

  • Architectural Security: The internal state management (including term registries and configuration variables) has been modernized to use true ECMAScript private fields (#), ensuring that Tempo's runtime state is strictly impenetrable from the outside.

[v3.6.0] - 2026-07-05 ​

✨ What's New β€” Shorthand Mutation Keys ​

Added native support for Tempo's shorthand format tokens (e.g., mi, ss, yy, ww) across both .add() and .set() mutations, streamlining developer experience and aligning TypeScript definitions with the underlying runtime engine.

✨ What's New β€” Shorthand Duration Keys ​

Expanded shorthand token support directly into the DurationModule. You can now seamlessly use shorthand keys for duration instantiation (Tempo.duration({ mi: 5 })), comparisons (t.until(other, 'mi')), and strict balancing (t.until(other).balance({ largestUnit: 'mi' })), bringing total API consistency across the core library.


[v3.5.2] - 2026-07-04 ​

✨ What's New β€” Minified Global Bundles ​

The build pipeline now natively produces highly optimized, minified IIFE bundles (*.min.js) for both Tempo Core and all Community Plugins, significantly reducing payload size for developers using CDN <script> tags.

Additionally, the browser-global export strategy has been re-architected. Both the core library and all <script> tag plugins now elegantly attach to a single, collision-free window.Magma namespace (e.g., window.Magma.Tempo and window.Magma.plugins.astro), dramatically improving developer experience and eliminating global variable pollution.

✨ What's New β€” Timezone Formatting Modifiers ​

The {tz} format token now natively supports a full suite of lowercase modifiers (:z, :zz, :zzz, :zzzz, :zzzzz)! This seamlessly outputs various localized timezone names and standard offset formats directly from the native Intl engine, eliminating the need to rely purely on raw IANA Timezone IDs for UI rendering.

πŸ—οΈ Internal Refactoring ​

  • Module Augmentation Typings: Hardened the "batteries-included" tempo.index.ts entry point by explicitly exporting core module types (e.g. DurationModule, FormatModule). This forces TypeScript to preserve their module augmentations in the compiled .d.ts bundle, guaranteeing that methods like .until() and .since() correctly appear in IDE autocomplete out-of-the-box.

[v3.5.1] - 2026-06-28 ​

πŸ—οΈ Internal Refactoring ​

  • Term Registration Resilience: Hardened Tempo.extend with structural deduplication to safely ignore redundant registrations of identical core terms. This prevents edge-case term collisions (e.g., qtr) in mixed module-loader environments like Vitest where Node ESM and Vite may evaluate plugins multiple times.

[v3.5.0] - 2026-06-28 ​

✨ What's New β€” Unified Plugin API ​

Tempo v3.5.0 introduces a brand new barrel export for plugin developers: @magmacomputing/tempo/plugin-api.

This new endpoint centralizes all plugin-authoring utilities (defineModule, definePlugin, defineTerm) and internal types into a single location. This architecture significantly cleans up application-level code by formally separating end-user imports from Plugin Developer imports.

If you are developing a custom plugin, you simply update your imports:

typescript
// Old Way
// import { defineModule } from '@magmacomputing/tempo/plugin';

// New Way
import { defineModule } from '@magmacomputing/tempo/plugin-api';

πŸ“š Documentation & Ecosystem ​

  • Static vs Smart CDNs: We have completely overhauled the installation documentation to clarify the distinction between using Smart CDNs (like esm.sh which automatically resolve dependencies) for prototyping, versus Static CDNs (with manual importmap configurations) for hardened production environments.
  • Evergreen Temporal Wording: Removed explicit version claims for upcoming Node.js native Temporal support, future-proofing our guides against shifting V8 release timelines.

[v3.4.0] - 2026-06-26 ​

✨ What's New β€” Dynamic Format Tokens ​

Tempo's formatting engine now supports completely custom format evaluators via the registry.tokens configuration. This allows you to define your own syntax tokens that execute complex math or delegate deeply localized formatting directly to the native Intl API.

typescript
Tempo.init({
	locale: 'fr-FR',
	registry: {
		tokens: {
			'wkd-fr': (zdt, { config }) => {
				const dtOptions = config?.intl?.dateTimeFormat ?? {};
				return zdt.toLocaleString(config?.locale ?? 'en', { ...dtOptions, weekday: 'long' });
			}
		}
	}
});

const t = new Tempo('2024-05-20');
t.format('{wkd-fr}'); // "lundi"

✨ Compound Token Modifiers ​

The compound date tokens ({dmy}, {mdy}, {ymd}) now support the :yy modifier to easily truncate their internal year components to 2 digits.

typescript
t.format('{dmy:yy}'); // "200524"

This officially supersedes the legacy *6 tokens (e.g., {dmy6}) which have now been deprecated from documentation to keep the API clean, though they remain fully supported in the engine for backwards compatibility.


[v3.3.1] - 2026-06-22 ​

✨ What's New β€” Slick Object Mutations ​

Tempo has always allowed jumping to boundaries using the Slick Shorthand (#qtr.>2q1) or semantic strings (next Friday). v3.3.1 extends this power directly to .set() object properties.

You can now use SLICK_KEYS (yy, mm, ww, dd, hh, mi, ss, wkd) as object keys in .set(), passing a directional string payload:

typescript
const t = new Tempo('2024-05-20'); // Monday

// Jump forward two months
t.set({ mm: '>2' }); // July 20

// Jump to the next Friday
t.set({ wkd: '>Fri' }); // May 24

// "Double-negation" math is fully supported:
t.set({ mm: '<-3' }); // Equivalent to >3

This makes relative programmatic date construction cleaner and keeps numeric jumps distinct from absolute assignments.

⚑ Extended Shorthand Modifiers ​

The Slick Regex parser has been upgraded to natively support equality logic and aliases. Modifiers like >=, <=, =, + (alias for >), and - (alias for <) are now fully supported for both numeric offsets and semantic loops (like wkd).

typescript
// Jump to next Monday, or stay on Monday if today is Monday
t.set({ wkd: '>=Mon' });

[v3.3.0] - 2026-06-21 ​

✨ What's New β€” Localized Modifier Registry ​

Tempo's relative-date keywords (next, last, this, ago, hence) were previously hardcoded as English-only constructs built into the core regex engine. v3.3.0 opens this up completely.

You can now register your own locale-specific words for any directional operator using registry.modifiers. These words integrate transparently with all standard parsing paths β€” prefix position, suffix position, and the high-performance # slick shorthand:

typescript
Tempo.init({
  locale: 'fr-FR',            // teaches Tempo French months & weekdays via Intl
  registry: {
    modifiers: {
      '>': ['prochain', 'suivant'],   // "next" synonyms
      '<': ['dernier', 'passΓ©'],      // "last / previous" synonyms
      '=': ['ce', 'cette'],           // "this" synonyms
    }
  }
});

new Tempo('vendredi prochain');    // βœ… "next Friday" β€” fully French
new Tempo('1 mai prochain');       // βœ… "next May 1st"
new Tempo('#qtr.dernier');         // βœ… "previous quarter" via slick shorthand

English keywords (next, last, ago, hence, this) remain active by default and are additively merged β€” you never lose built-in behaviour when adding your own.

πŸ—οΈ Internal Refactoring ​

  • Frozen Default Registry Fixed: The internal Default configuration object is wrapped in a deep-freeze Proxy (secure()). Previously, every Tempo.init() call silently failed to write formats, locales, and modifiers into the frozen registry sub-object, logging three setProperty warnings per call and abandoning the writes. The registry is now correctly shallow-cloned into a mutable copy on initialization.

  • Lexer Token Cleanup: All hardcoded English modifier keywords have been stripped from the core regex tokens (Match.modifier, Match.shorthand, Match.slick). The engine now operates purely on symbolic operators (>, <, =, +, -) internally and resolves all natural-language words through the registry at runtime.

  • Pre-filter Guard Accuracy: Refined the numeric-safety guard bypass to trigger only when the input actually contains a registered modifier keyword. Previously the guard was bypassed unconditionally whenever modifier config was present, which could silently accept invalid nanosecond epoch strings.

⚑ Slick Modifier Semantics ​

Localized slick modifiers behave identically to their symbolic counterparts. #qtr.prochain is an exact alias for #qtr.>:

  • From inside Q2 (any day from April 1 to June 29) β†’ July 1 (start of Q3)
  • From June 30 (last day of Q2) β†’ July 1 (start of Q3)
  • From July 1 (first day of Q3) β†’ October 1 (start of Q4)

This mirrors how next Friday works: from any non-Friday you get the very next Friday; if you are already on Friday, you get the following Friday. Fully deterministic β€” "next" always means "the start of the next occurrence of this term".


[v3.2.3] - 2026-06-20 ​

✨ What's New β€” Project Scaffolding ​

  • tempo.config.ts Pattern: Introduced centralized project configuration via a discoverable tempo.config.ts / tempo.config.js file. This mirrors the vite.config.ts / tailwind.config.js convention β€” one file, one place, loaded once.
  • Tempo.bootstrap(): A new async entry point that auto-discovers and loads your tempo.config.ts before any domain logic runs. Safe to await at application startup.
  • CLI Scaffold: npx @magmacomputing/tempo scaffold:all bootstraps a tempo.config.ts and HTML sandbox into your project in seconds.

[v3.2.2] - 2026-06-18 ​

✨ What's New ​

  • Compact Date Tokens: New 6-digit compact format tokens {dmy6}, {mdy6}, {ymd6} (e.g. 200626), plus ISO week-of-year helpers {yywy} and {yyww}.
  • {wy} Rename: The former {ww} token is now {wy} (week-of-year) to eliminate visual ambiguity with structural format tokens.

πŸ—οΈ Internal Refactoring ​

  • Recursive deepMerge Hardened: The Intl options merge pipeline now uses a fully recursive deepMerge rather than a shallow spread, preventing nested keys like intl.dateTimeFormat from clobbering intl.relativeTimeFormat.
  • Prototype Pollution Guards: Added strict guards against __proto__, constructor, and prototype key assignments in deepMerge and deepFreeze utilities.

[v3.2.1] - 2026-06-17 ​

✨ What's New ​

  • Ordinal Localization Fallback: Added support for custom Intl.PluralRules dictionaries. By supplying an ordinal dictionary inside your global locales registry, Tempo natively evaluates the active plural category (e.g., 'one', 'other') and appends the localized suffix automatically (such as '1er' and '15e' for French).

πŸ“š Documentation & Ecosystem ​

  • Improved Cookbook Ergonomics: Extensively reorganized the tempo.cookbook.md to make it easier to read. Related functionality is now logically grouped togetherβ€”for example, merging native and semantic .add() math examples, and expanding on boundary .set() capabilities.
  • Clarified Configurations: Updated tempo.config.md to remove outdated properties and explicitly document nested options like intl.durationFormat.
  • REPL Traps: Added prominent warnings to the documentation about the strict idempotency of Tempo.init(), helping new developers avoid silent configuration failures in hot-reload and REPL environments.

πŸ—οΈ Internal Refactoring ​

  • Alias Collision Prevention: Hardened the sandbox alias detection engine to prevent redundant collision warnings in the console when Tempo.init is invoked in sandboxed contexts.

[v3.2.0] - 2026-06-16 ​

✨ What's New ​

  • Multi-lingual Parsing: The locale configuration property now officially accepts an array of strings (string | string[]). This enables the ParseModule to intelligently extract terminology from multiple languages simultaneously, generating a single engine capable of parsing dates from any of the specified locales interchangeably.
  • Intl.DateTimeFormatOptions Passthrough: The .format() method now officially supports passing a native Intl.DateTimeFormatOptions object. This provides a highly flexible, "humanized" wrapper around the rigid Temporal API for complex cultural formatting (e.g., Arabic numerals, Japanese Reiwa eras).
  • BigInt Overload for Epoch Nanoseconds: The {nano} formatting token (epoch nanoseconds) correctly coerces to and returns a precision-preserving BigInt instead of a string, bypassing standard Number limits.

πŸ“š Documentation & Ecosystem ​

  • Domain-Locked Licensing: Stabilized the premium plugin licensing engine with a robust domain-locked validation mechanism.
  • SSR & VitePress Fixes: Fixed Temporal is not defined crashes during SSR builds and simplified our documentation pipeline by removing heavy Markdown plugins.
  • New Locale Guides: Added comprehensive Internationalization (tempo.locale.md) guides to the primary navigation structure.

πŸ—οΈ Internal Refactoring ​

  • O(1) Locale Traceability: Upgraded the internal dictionary architecture. The Normalizer can now resolve the winning language of a matched token in pure O(1) time without any expensive Regex sub-capture scanning.
  • Polyfill Formatting Bypass: Bypassed a known bug in the Temporal polyfill's toLocaleString() method that incorrectly dropped Kanji constraints in Japanese formatting contexts, guaranteeing precise Intl fallback correctness.
  • Parser Map Safety: Architecturally split the internal reverse-lookup into distinct monthMap and weekdayMap dictionaries, eliminating the risk of cross-locale abbreviation collisions (e.g., if "mai" is a month in one language but a weekday in another).

[v3.1.0] - 2026-06-13 ​

✨ What's New ​

  • Chained Formatting Modifiers: A powerful new format modifier engine ({mon:locale:upper}) allowing dynamic casing (:upper, :lower), ordinal suffixes (:ord), and deep localization (:locale) dynamically via the native Intl API.
  • Auto-Localization Engine: Global configurations for format: { localize: true } and parse: { localize: true } provide a massive leap forward in out-of-the-box internationalization. Tempo can now intelligently parse localized input (months, weekdays, relative terms like 'demain') and automatically format localized output using memoized, high-performance Intl strategies.
  • Global locales Registry: Centralized management for augmenting specific term strings per locale globally across instances via Tempo.init({ locale: 'fr-FR', registry: { locales: { ... } } }).

πŸ—οΈ Internal Refactoring ​

  • Intl Instantiation: Upgraded internal architectures to memoize and pool Intl.DateTimeFormat objects seamlessly, ensuring parsing localization generation and output formatting impose virtually zero performance hit on hot execution paths.
  • Term Localization: Upgraded the Term formatting resolution pipeline to support falling back across a strict precedence: Global Registry > Plugin Bundled Dictionary > term's existing label/value.

[v3.0.0] - 2026-06-08 ​

🚨 Major Breaking Changes ​

  • Term Registry Consolidation: Removed the legacy and deprecated term property from the Discovery configuration object. All Term-based plugins must now be registered via the terms (plural) array.
  • Shorthand Configuration Removal: Removed support for shorthand root-level properties in the Discovery object that have been superseded by nested configuration groups:
    • relativeTime shorthand has been removed; use intl.relativeTime instead.
    • term shorthand has been removed; use terms instead.
  • Strict Parsing Mode: The parser now enforces a stricter guard check by default, reducing the likelihood of "false positive" matches on ambiguous strings.
  • Ticker Module Extraction: To lighten the core bundle, the TickerPlugin has been extracted into its own standalone premium plugin (@magmacomputing/tempo-plugin-ticker). It is protected by a License Key via the Tempo Registry.

✨ What's New ​

  • Formatting Module Additions: Added new compact date tokens ({dmy}, {mdy}, {ymd}) for generating 8-digit compact date strings (e.g. 24102026). {hhmiss} has been renamed to {hms} for consistency.
  • Ordinal Tokens: Uppercase variants of standard date tokens ({DAY}, {WW}, {MM}) now output their ordinal string representation (e.g., 24th, 1st, 2nd).

πŸ“¦ Migration Path for Tempo.ticker() Users ​

If you are upgrading from v2.x and your application relies on Tempo.ticker(), you will need to update your integration:

  1. Install the Plugin: npm install @magmacomputing/tempo-plugin-ticker
  2. Activate your License: Obtain your free JWT license key.
    Tempo License Registry
    πŸ‘‰ Go to the Tempo License Registry πŸ‘ˆ
    Manage your subscriptions and retrieve your license key.
  3. Register the Plugin: Wire the key into your application and extend Tempo:
    javascript
    import { Tempo } from '@magmacomputing/tempo';
    import { TickerPlugin } from '@magmacomputing/tempo-plugin-ticker';
    
    // Wire your license key
    Tempo.init({ license: 'YOUR_JWT_KEY' });
    
    // Register the extracted plugin
    Tempo.extend(TickerPlugin);

πŸ—οΈ Internal Refactoring ​

  • Zero-Fallback Initialization: Cleaned up the Tempo.init() bootstrap logic to remove legacy compatibility layers, resulting in a cleaner internal state and reduced bundle size.
  • Build Pipelines: Fully synchronized build pipelines and TS declarations to ensure vitest and tsc operate seamlessly across local and premium workspaces.

Released under the MIT License.