Skip to content

Calendar Units Package ​

The @usetemporal/calendar-units package provides specialized time units designed for calendar user interfaces, following useTemporal's philosophy of keeping the core minimal while offering powerful extensions.

Overview ​

While useTemporal's core provides fundamental time operations, calendar UIs often need specialized behavior. The calendar-units package addresses these needs without bloating the core library.

Installation ​

bash
npm install @usetemporal/calendar-units @usetemporal/core

Available Units ​

stableMonth ​

The stableMonth unit always returns a 42-day (6-week) period, ensuring calendar grids maintain consistent height regardless of the actual month length.

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

const temporal = createTemporal({
  adapter: createNativeAdapter({ weekStartsOn: 1 }), // Monday
});

const stableMonth = period(temporal, 'stableMonth', temporal.browsing.value);
const days = divide(temporal, stableMonth, 'day');
console.log(days.length); // Always 42

Why Use Calendar Units? ​

Consistent Layouts ​

Regular months vary from 28-31 days and can span 4-6 weeks when displayed in a grid. This causes:

  • Layout shifts when navigating between months
  • Complex CSS calculations
  • Poor user experience with jumping content

Better Performance ​

With a fixed 42-day grid:

  • Predictable memory allocation
  • Cacheable layouts
  • Optimized rendering

Simplified Development ​

  • No edge case handling for different month lengths
  • Consistent styling rules
  • Easier responsive design

Integration with Core ​

Calendar units integrate seamlessly with all useTemporal operations:

typescript
// Navigation
const nextMonth = next(temporal, temporal.browsing.value);
const nextStable = period(temporal, 'stableMonth', nextMonth);

// Division
const weeks = divide(temporal, stableMonth, 'week'); // Always 6 weeks
const days = divide(temporal, stableMonth, 'day');   // Always 42 days

// Comparison
const isInGrid = contains(stableMonth, someDayPeriod);

Examples ​

Basic Calendar Grid ​

typescript
function createCalendarGrid(date: Date) {
  const temporal = createTemporal({
    adapter: createNativeAdapter(),
    weekStartsOn: 1,
    date,
  });

  const stableMonth = period(temporal, 'stableMonth', temporal.browsing.value);
  const weeks = divide(temporal, stableMonth, 'week');
  
  return weeks.map(week => divide(temporal, week, 'day'));
}

Identifying Current Month Days ​

typescript
const currentMonth = temporal.browsing.value.date.getMonth();
const days = divide(temporal, stableMonth, 'day');

const currentMonthDays = days.filter(day => 
  day.date.getMonth() === currentMonth
);
const paddingDays = days.filter(day => 
  day.date.getMonth() !== currentMonth
);

Migration Guide ​

If you're currently using manual stable month implementations, see our migration guide for step-by-step instructions.

Performance Considerations ​

  • Generation: O(1) - Fixed 42 iterations
  • Memory: ~8.4KB for full day grid
  • Caching: Results are cacheable by month/year key

See the performance guide for optimization strategies.

TypeScript Support ​

Full TypeScript support with automatic type augmentation:

typescript
// Automatically registered when imported
import '@usetemporal/calendar-units';

// TypeScript knows about the new unit
const period = period(temporal, 'stableMonth', browsing);

Future Units ​

The calendar-units package sets the foundation for additional calendar-specific units:

  • businessWeek - 5-day business weeks
  • fiscalQuarter - Company fiscal quarters
  • academicSemester - School calendar periods

Resources ​

Released under the MIT License.