Skip to content

Calendar Units API

Installation

bash
npm install @usetemporal/calendar-units

Import

typescript
import '@usetemporal/calendar-units';

Units

stableMonth

A time unit that always returns a 42-day period (6 complete weeks) for consistent calendar layouts.

Type Definition

typescript
interface StableMonthUnit extends Unit {
  type: 'stableMonth';
  divisions: ['week', 'day'];
  mergesTo: 'year';
}

Behavior

  • Always returns exactly 42 days (6 weeks)
  • Starts on the configured weekStartsOn day
  • Includes days from previous/next months as needed
  • Validated by checking the period spans exactly 42 days

Usage

typescript
import { period, divide } from '@usetemporal/core';
import '@usetemporal/calendar-units';

// Create a stableMonth period
const period = period(temporal, 'stableMonth', temporal.browsing.value);

// Divide into weeks (always returns 6)
const weeks = divide(temporal, period, 'week');

// Divide into days (always returns 42)
const days = divide(temporal, period, 'day');

Grid Calculation

  1. Find the first day of the target month
  2. Back up to the start of that week (based on weekStartsOn)
  3. Extend forward exactly 42 days (6 complete weeks)

Examples

Different Week Starts
typescript
// Sunday start (US convention)
const sundayTemporal = createTemporal({
  adapter: createNativeAdapter(),
  weekStartsOn: 0,
});

// Monday start (ISO convention)
const mondayTemporal = createTemporal({
  adapter: createNativeAdapter(),
  weekStartsOn: 1,
});
Edge Cases
typescript
// February - shortest month
const feb2024 = period(temporal, 'stableMonth', {
  date: new Date(2024, 1, 1)
});
// Still returns 42 days, including Jan and March days

// December - year boundary
const dec2024 = period(temporal, 'stableMonth', {
  date: new Date(2024, 11, 1)
});
// May include days from January 2025

Helper Functions

createStableMonth

Utility function for creating stableMonth periods with proper week alignment.

typescript
function createStableMonth(temporal: Temporal, date: Date): Period

Parameters

  • temporal - The temporal instance with adapter and weekStartsOn configuration
  • date - Any date within the target month

Returns

A Period object with:

  • type: 'stableMonth'
  • start - First day of the 6-week grid
  • end - Last moment of the 42nd day
  • date - Reference date (first of the month)

Example

typescript
import { createStableMonth } from '@usetemporal/calendar-units';

const stableMonth = createStableMonth(temporal, new Date(2024, 0, 15));
// Returns 42-day grid for January 2024

Integration with Core Operations

divide()

typescript
const stableMonth = period(temporal, 'stableMonth', browsing);

// By week - always returns 6 periods
const weeks = divide(temporal, stableMonth, 'week');
console.log(weeks.length); // 6

// By day - always returns 42 periods  
const days = divide(temporal, stableMonth, 'day');
console.log(days.length); // 42

contains()

typescript
const stableMonth = period(temporal, 'stableMonth', browsing);
const someDay = period(temporal, 'day', { date: someDate });

if (contains(stableMonth, someDay)) {
  // Date is within the 42-day grid
}

Note: Navigation operations (next/previous) work with the underlying month, not the stable grid:

typescript
// Navigate to next month
const nextMonth = next(temporal, temporal.browsing.value);

// Create stable grid for that month
const nextStable = period(temporal, 'stableMonth', nextMonth);

TypeScript

Module Augmentation

The package automatically augments the UnitRegistry when imported:

typescript
declare module '@usetemporal/core' {
  interface UnitRegistry {
    stableMonth: true;
  }
}

Type Safety

All useTemporal functions recognize 'stableMonth' as a valid unit:

typescript
// Full type checking and autocompletion
period(temporal, 'stableMonth', browsing); // ✓
hasUnit('stableMonth'); // true
getUnitDefinition('stableMonth'); // Returns unit definition

Performance

Computational Cost

  • Period creation: O(1)
  • Division by day: O(42) - fixed iterations
  • Division by week: O(6) - fixed iterations

Memory Usage

  • Single period: ~200 bytes
  • Full day grid: ~8.4 KB (42 periods)
  • Full week grid: ~1.2 KB (6 periods)

Optimization Tips

typescript
// Cache for repeated access
const cache = new Map<string, Period[]>();

function getCachedGrid(temporal: Temporal, date: Date) {
  const key = `${date.getFullYear()}-${date.getMonth()}`;
  
  if (!cache.has(key)) {
    const period = period(temporal, 'stableMonth', { date });
    cache.set(key, divide(temporal, period, 'day'));
  }
  
  return cache.get(key)!;
}

Compatibility

  • Works with all useTemporal adapters
  • No additional dependencies
  • Tree-shakeable
  • ~1KB gzipped

Released under the MIT License.