Migration Guide
This guide helps you migrate from popular date libraries to useTemporal. Each section provides direct comparisons and migration strategies.
Breaking Changes in v2.0.0
Removal of toPeriod Function
The toPeriod function has been removed in v2.0.0 as part of our API simplification efforts. toPeriod was just a wrapper around period with the same functionality.
Before (v1.x)
import { toPeriod } from '@allystudio/usetemporal';
const dayPeriod = toPeriod(temporal, new Date(), 'day');
const monthPeriod = toPeriod(temporal, date, 'month');After (v2.0.0)
Level 1 (Pure Functions):
import { period } from '@allystudio/usetemporal/operations';
import { createNativeAdapter } from '@allystudio/usetemporal/native';
const adapter = createNativeAdapter();
const dayPeriod = period(adapter, new Date(), 'day');
const monthPeriod = period(adapter, date, 'month');Level 2 (Builder):
import { createTemporal } from '@allystudio/usetemporal';
import { createNativeAdapter } from '@allystudio/usetemporal/native';
const temporal = createTemporal({
adapter: createNativeAdapter(),
date: new Date()
});
const dayPeriod = temporal.period(new Date(), 'day');
const monthPeriod = temporal.period(date, 'month');This requires updating the function signature - toPeriod doesn't exist in v2.0.
Rename of createPeriod to period
The createPeriod function has been renamed to period in v2.0.0 to follow a cleaner, more mathematical API style. The function behaves identically - only the name has changed.
Before (v1.x)
import { createPeriod } from '@allystudio/usetemporal';
const dayPeriod = createPeriod(temporal, new Date(), 'day');
const monthPeriod = createPeriod(temporal, date, 'month');After (v2.0.0)
Level 1 (Pure Functions):
import { period } from '@allystudio/usetemporal/operations';
import { createNativeAdapter } from '@allystudio/usetemporal/native';
const adapter = createNativeAdapter();
const dayPeriod = period(adapter, new Date(), 'day');
const monthPeriod = period(adapter, date, 'month');Level 2 (Builder):
import { createTemporal } from '@allystudio/usetemporal';
import { createNativeAdapter } from '@allystudio/usetemporal/native';
const temporal = createTemporal({
adapter: createNativeAdapter(),
date: new Date()
});
const dayPeriod = temporal.period(new Date(), 'day');
const monthPeriod = temporal.period(date, 'month');Note: The function signature has changed - adapter is now the first parameter for pure functions.
Merge of createCustomPeriod into period
The createCustomPeriod function has been merged into the period function in v2.0.0 through function overloading. This reduces the API surface while maintaining all functionality.
Before (v1.x)
import { createCustomPeriod } from '@allystudio/usetemporal';
const customPeriod = createCustomPeriod(startDate, endDate);After (v2.0.0)
Level 1 (Pure Functions):
import { period } from '@allystudio/usetemporal/operations';
import { createNativeAdapter } from '@allystudio/usetemporal/native';
const adapter = createNativeAdapter();
const customPeriod = period(adapter, { start: startDate, end: endDate });Level 2 (Builder):
import { createTemporal } from '@allystudio/usetemporal';
import { createNativeAdapter } from '@allystudio/usetemporal/native';
const temporal = createTemporal({
adapter: createNativeAdapter(),
date: new Date()
});
const customPeriod = temporal.period({ start: startDate, end: endDate });The period function now accepts two signatures:
period(adapter, date, unit)- Creates a standard period (Level 1)period(adapter, { start, end })- Creates a custom period (Level 1)temporal.period(date, unit)- Builder API (Level 2)temporal.period({ start, end })- Builder API (Level 2)
StableMonth Moved to Calendar Units Package
The stableMonth unit has been moved from the core library to the @allystudio/usetemporal/calendar package in v2.0.0. This keeps the core library focused on fundamental operations while providing calendar-specific features as an optional enhancement.
Before (v1.x)
import { period, STABLE_MONTH } from '@allystudio/usetemporal';
const stableMonth = period(temporal, 'stableMonth', date);
// or
const stableMonth = period(temporal, STABLE_MONTH, date);After (v2.0.0)
Install the calendar units package:
npm install @allystudio/usetemporal/calendarThen use it:
import { period } from '@allystudio/usetemporal';
import '@allystudio/usetemporal/calendar'; // Registers stableMonth unit
const stableMonth = period(temporal, 'stableMonth', temporal.browsing.value);
const days = divide(temporal.adapter, stableMonth, 'day'); // Always 42 daysManual Implementation (if not using calendar-units)
// Generate 6-week calendar grid manually
const month = period(temporal, 'month', date);
const weeks = divide(temporal.adapter, month, 'week');
// Get all weeks that touch this month
const firstWeek = weeks[0];
const prevWeek = previous(temporal.adapter, firstWeek);
const allWeeks = [prevWeek, ...weeks];
// Ensure 6 weeks total
while (allWeeks.length < 6) {
const lastWeek = allWeeks[allWeeks.length - 1];
allWeeks.push(next(temporal.adapter, lastWeek));
}
// Get all days
const days = allWeeks.flatMap(week => divide(temporal.adapter, week, 'day'));See Calendar Units for more details.
Migration from Moment.js
Basic Date Operations
Moment.js
import moment from "moment";
// Current time
const now = moment();
// Specific date
const date = moment("2024-03-14");
// Format
const formatted = moment().format("YYYY-MM-DD");
// Add/subtract
const tomorrow = moment().add(1, "day");
const yesterday = moment().subtract(1, "day");useTemporal
import { createTemporal } from "@allystudio/usetemporal";
import { createNativeAdapter } from "@allystudio/usetemporal/native";
const temporal = createTemporal({ adapter: createNativeAdapter() });
// Current time
const now = temporal.now;
// Specific date
const date = new Date("2024-03-14");
const day = temporal.periods.day(temporal, { date });
// Format (through adapter or native)
const formatted = day.start.toISOString().split("T")[0];
// Add/subtract
const tomorrow = day.future();
const yesterday = day.past();Start/End of Period
Moment.js
// Start of month
const startOfMonth = moment().startOf("month");
// End of month
const endOfMonth = moment().endOf("month");
// Start of week
const startOfWeek = moment().startOf("week");useTemporal
// Start/end of month
const month = temporal.periods.month(temporal);
const startOfMonth = month.start;
const endOfMonth = month.end;
// Start/end of week
const week = temporal.periods.week(temporal);
const startOfWeek = week.start;
const endOfWeek = week.end;Working with Weeks
Moment.js
// Get week number
const weekNumber = moment().week();
// Get all days in week
const days = [];
const startOfWeek = moment().startOf("week");
for (let i = 0; i < 7; i++) {
days.push(startOfWeek.clone().add(i, "days"));
}useTemporal
// Get week number
const week = temporal.periods.week(temporal);
const weekNumber = week.number;
// Get all days in week - much simpler!
const days = temporal.divide(week, "day");Relative Time
Moment.js
// Check if date is in the past
const isPast = moment("2023-01-01").isBefore(moment());
// Check if date is today
const isToday = moment().isSame(date, "day");
// Get days in month
const daysInMonth = moment().daysInMonth();useTemporal
// Check if date is in the past
const day = temporal.periods.day(temporal, { date: new Date("2023-01-01") });
const isPast = day.isPast;
// Check if date is today
const isToday = day.isNow;
// Get days in month
const month = temporal.periods.month(temporal);
const daysInMonth = month.days;Migration from date-fns
Basic Operations
date-fns
import {
format,
addDays,
startOfMonth,
endOfMonth,
getWeek,
eachDayOfInterval,
} from "date-fns";
const now = new Date();
// Format date
const formatted = format(now, "yyyy-MM-dd");
// Add days
const tomorrow = addDays(now, 1);
// Get start/end of month
const monthStart = startOfMonth(now);
const monthEnd = endOfMonth(now);
// Get week number
const weekNum = getWeek(now);
// Get all days in a range
const days = eachDayOfInterval({
start: monthStart,
end: monthEnd,
});useTemporal
const temporal = createTemporal({ adapter: createNativeAdapter() });
// Current date
const now = temporal.now;
// Format date (use adapter or native)
const formatted = now.toISOString().split("T")[0];
// Add days
const today = temporal.periods.day(temporal);
const tomorrow = today.future();
// Get start/end of month
const month = temporal.periods.month(temporal);
const monthStart = month.start;
const monthEnd = month.end;
// Get week number
const week = temporal.periods.week(temporal);
const weekNum = week.number;
// Get all days in month - much simpler!
const days = temporal.divide(month, "day");Advanced date-fns with useTemporal Adapter
For a smoother migration, use the date-fns adapter:
import { createTemporal } from "@allystudio/usetemporal";
import { createDateFnsAdapter } from "@allystudio/usetemporal/date-fns";
import { format } from "date-fns";
const temporal = createTemporal({
adapter: createDateFnsAdapter(),
});
// Now you can use date-fns functions on useTemporal dates
const month = temporal.periods.month(temporal);
const formatted = format(month.start, "MMMM yyyy"); // "March 2024"
// But also get useTemporal's powerful features
const weeks = temporal.divide(month, "week");
const days = temporal.divide(month, "day");Migration from Day.js
Basic Operations
Day.js
import dayjs from "dayjs";
// Current time
const now = dayjs();
// Parse date
const date = dayjs("2024-03-14");
// Format
const formatted = dayjs().format("YYYY-MM-DD");
// Chain operations
const result = dayjs().startOf("month").add(1, "week").endOf("day");
// Get/set
const year = dayjs().year();
const month = dayjs().month(); // 0-11useTemporal
const temporal = createTemporal({ adapter: createNativeAdapter() });
// Current time
const now = temporal.now;
// Work with specific date
const date = new Date("2024-03-14");
const day = temporal.periods.day(temporal, { date });
// Format
const formatted = day.start.toISOString().split("T")[0];
// Equivalent operations
const month = temporal.periods.month(temporal);
const firstWeek = temporal.divide(month, "week")[0];
const endOfFirstWeek = firstWeek.end;
// Get values - note month is 1-12!
const year = temporal.periods.year(temporal);
const monthUnit = temporal.periods.month(temporal);
console.log(year.number); // 2024
console.log(monthUnit.number); // 3 (March, not 2!)Migration from Luxon
Basic Operations
Luxon
import { DateTime } from "luxon";
// Current time
const now = DateTime.now();
// Create date
const date = DateTime.fromISO("2024-03-14");
// With timezone
const ny = DateTime.now().setZone("America/New_York");
// Format
const formatted = now.toFormat("yyyy-MM-dd");
// Start of period
const startOfMonth = now.startOf("month");
// Add duration
const tomorrow = now.plus({ days: 1 });useTemporal with Luxon Adapter
import { createTemporal } from "@allystudio/usetemporal";
import { createLuxonAdapter } from "@allystudio/usetemporal/luxon";
const temporal = createTemporal({
adapter: createLuxonAdapter(),
timeZone: "America/New_York", // planned feature
});
// Current time
const now = temporal.now;
// Work with specific date
const date = new Date("2024-03-14");
const day = temporal.periods.day(temporal, { date });
// Format using Luxon through the adapter
const formatted = temporal.adapter.format(day.start, "yyyy-MM-dd");
// Start of period
const month = temporal.periods.month(temporal);
const startOfMonth = month.start;
// Navigation
const tomorrow = day.future();Migration from Native Date
Basic Operations
Native JavaScript Date
// Current time
const now = new Date();
// Create date
const date = new Date(2024, 2, 14); // March 14 (month is 0-indexed!)
// Get components
const year = date.getFullYear();
const month = date.getMonth(); // 0-11
const day = date.getDate();
// Add days (manual calculation)
const tomorrow = new Date(now);
tomorrow.setDate(tomorrow.getDate() + 1);
// Get first day of month (manual)
const firstDay = new Date(date.getFullYear(), date.getMonth(), 1);
// Get last day of month (manual)
const lastDay = new Date(date.getFullYear(), date.getMonth() + 1, 0);useTemporal
const temporal = createTemporal({ adapter: createNativeAdapter() });
// Current time
const now = temporal.now;
// Work with specific date
const date = new Date(2024, 2, 14); // Still March 14
const day = temporal.periods.day(temporal, { date });
// Get components - month is 1-12!
const year = temporal.periods.year(temporal);
const month = temporal.periods.month(temporal);
console.log(year.number); // 2024
console.log(month.number); // 3 (not 2!)
console.log(day.number); // 14
// Add days - much simpler
const tomorrow = day.future();
// Get first/last day of month - automatic
const monthUnit = temporal.periods.month(temporal);
const firstDay = monthUnit.start;
const lastDay = monthUnit.end;Common Migration Patterns
1. Calendar Generation
Traditional Approach
// Complex logic to generate calendar with any library
function generateCalendar(year, month) {
const firstDay = new Date(year, month, 1);
const lastDay = new Date(year, month + 1, 0);
const days = [];
// Add padding days from previous month
const firstDayOfWeek = firstDay.getDay();
for (let i = firstDayOfWeek - 1; i >= 0; i--) {
days.push(new Date(year, month, -i));
}
// Add days of current month
for (let i = 1; i <= lastDay.getDate(); i++) {
days.push(new Date(year, month, i));
}
// Add padding days from next month
// ... more complex logic
return days;
}useTemporal Approach
// Simple and clear with useTemporal
function generateCalendar(temporal) {
const month = temporal.periods.month(temporal);
const weeks = temporal.divide(month, "week");
// Get all days from all weeks that touch this month
const days = weeks.flatMap(week => temporal.divide(week, "day"));
return days; // Includes padding days for complete weeks
}2. Week-Based Calculations
Traditional Approach
// Get all weeks in a month (complex)
function getWeeksInMonth(date) {
const startOfMonth = moment(date).startOf("month");
const endOfMonth = moment(date).endOf("month");
const weeks = [];
let current = startOfMonth.clone().startOf("week");
while (current.isSameOrBefore(endOfMonth)) {
weeks.push(current.clone());
current.add(1, "week");
}
return weeks;
}useTemporal Approach
// Get all weeks in a month (simple)
function getWeeksInMonth(temporal) {
const month = temporal.periods.month(temporal);
const weeks = temporal.divide(month, "week");
return weeks; // That's it!
}3. Reactive Date Updates
Traditional Approach
// Manual tracking with other libraries
let currentDate = moment();
let subscribers = [];
function updateDate(newDate) {
currentDate = newDate;
subscribers.forEach((fn) => fn(currentDate));
}
function subscribe(fn) {
subscribers.push(fn);
}useTemporal Approach
// Automatic reactivity
import { watch } from "@vue/reactivity";
const temporal = createTemporal({ adapter: createNativeAdapter() });
const month = temporal.periods.month(temporal);
// Automatically updates when date changes
watch(
() => month.number,
(newMonth) => {
console.log(`Month changed to ${newMonth}`);
}
);Migration Checklist
When migrating to useTemporal:
Install useTemporal and choose an adapter
bashnpm install @allystudio/usetemporal # or with your preferred adapter (luxon or date-fns) npm install @allystudio/usetemporal luxon # or npm install @allystudio/usetemporal date-fnsUpdate imports
- Remove old date library imports
- Import createTemporal and your chosen adapter
Initialize temporal instance
javascriptconst temporal = createTemporal({ adapter: createNativeAdapter({ weekStartsOn: 1 }), // Configure as needed });Replace date operations
- Use periods for accessing time units
- Use divide() for getting collections
- Use future()/past() for navigation
Update month indexing
- Remember: useTemporal months are 1-12, not 0-11
Leverage reactive features
- Use isNow, isPast, isFuture properties
- Set up watchers for reactive updates
Simplify complex date logic
- Replace manual calculations with divide()
- Use week-based calendar generation
Gradual Migration Strategy
You don't have to migrate everything at once:
// Phase 1: Use useTemporal for new features
const temporal = createTemporal({ adapter: createNativeAdapter() });
// Phase 2: Keep existing date library for formatting
import { format } from "date-fns";
// Phase 3: Combine both during transition
const month = temporal.periods.month(temporal);
const formatted = format(month.start, "MMMM yyyy");
// Phase 4: Gradually replace old patterns
const days = temporal.divide(month, "day"); // Instead of eachDayOfIntervalNeed Help?
- Check the API Reference for detailed documentation
- See Examples for common use cases
- Review Advanced Patterns for complex scenarios
The useTemporal community is here to help make your migration smooth and successful!