Mutation & Math
Tempo's API for modifying instances is intentionally microscopic. Rather than bloating the prototype with dozens of distinct methods (.add(), .subtract(), .startOf(), etc.), Tempo provides unified utilities that natively support intuitive shorthand strings.
Immutability & Chainability
All mutation methods in Tempo (.add(), .set()) are strictly immutable. They never modify the original instance. Instead, they evaluate the change and return a new Tempo instance, ensuring absolute safety and allowing for predictable method chaining.
The .add() Method
The .add() method returns a new Tempo instance shifted by a specific amount.
const t = tempo();
t.add({ days: 5 }); // Adds 5 daysWhere is .subtract()?
Design Choice
Where is .subtract()? Tempo keeps its core API intentionally microscopic. Because .add() natively supports negative durations and Tempo's Slick math provides directional operators (e.g., t.add('<5d') or t.add({ days: -5 })), a separate .subtract() method is mathematically redundant. We chose a smaller bundle size over duplicate methods.
You can subtract time simply by using negative values:
t.add({ days: -5 }); // Subtracts 5 daysOr using Slick Math:
t.add('>5d'); // Adds 5 days
t.add('<5d'); // Subtracts 5 daysThe .set() Method
While .add() shifts a date, the .set() method replaces components.
t.set({ year: 2026, month: 1 }); // Sets to January 2026Navigating to Boundaries
Slick Math also works inside .set() for boundary navigation:
t.set('start.month'); // Start of the current month
t.set('end.year'); // End of the current yearSlick Object Mutations
You can also navigate relative to your current date by using Slick Shorthand operators directly inside the .set() object payload. Use the snippet shorthand keys (yy, mm, ww, dd, wkd, etc.) and provide a string payload containing a directional modifier:
const t = new Tempo('2024-05-20'); // Monday
// Jump forward two months
t.set({ mm: '>2' }); // July 20th
// Jump to the next Friday
t.set({ wkd: '>Fri' }); // May 24thBecause .set() processes keys in insertion order, you can now effortlessly combine absolute assignments and Slick shifts in a single pass to build complex boundaries:
// Jump 2 months forward, find the next Friday, and set the time to 10:30 AM
const t2 = t.set({
mm: '>2',
wkd: '>Fri',
hour: 10,
minute: 30
});⚠️ ESLint sort-keys Warning
Because mixed object payloads execute strictly in the order they are defined, you must be careful if you use aggressive automated linters (like ESLint's sort-keys auto-fixer). If your linter alphabetically re-orders your properties, your math will execute in the wrong order! If your codebase forces alphabetical object keys, stick to chaining: t.set({ mm: '>2' }).set({ wkd: '>Fri' }).
💡 Why can't I use Slick modifiers on timezones (tzd)?
Changing a timezone (tzd or timeZone) does not traverse the timeline—it merely changes the local representation of the exact same absolute moment in time. Because no temporal displacement occurs, applying directional Slick modifiers (like >) to a timezone is logically invalid and unsupported.
Chainability
Because all mutations return a new instance, you can safely chain .add() and .set() methods together to perform complex temporal logic in a single, readable line.
const endOfQ1 = t
.set('start.year') // Snap to January 1st
.add('>3mm') // Shift forward 3 months (to April 1st)
.set('end.month'); // Snap to April 30th at 23:59:59.999Relational vs. Navigation Shifting
When using custom terminology plugins (like Fiscal Quarters or Seasons), Tempo provides two distinct shorthand styles for mutation:
1. Navigation Mode (String)
Use a string to jump to a specific boundary. This relies on chronological momentum.
t.set('#qtr.>q1'); // Snaps to the start of the next Q1
t.add('#timeOfDay.>afternoon'); // Jumps to the start of the next Afternoon2. Relational Mode (Object)
Use an object to shift by a specific semantic step while preserving your relative position in the cycle.
t.add({ '#qtr': 1 }); // Shift forward 1 quarter, preserving progressIf you are 20 days into Q1, relational shifting will put you exactly 20 days into Q2.
👉 Learn More: For deeper details on cycle preservation and directional operators, see the Shorthand Engine Reference.