| name | tsentials-time |
| description | Use when you need testable time — DateTimeProvider interface with utcNow()/utcNowDate()/utcNowMs() so production code uses the SystemDateTimeProvider const object while tests use createFakeDateTimeProvider to freeze, advance, or set the clock without touching Date.now(). |
tsentials/time
Testable time abstraction. Never call Date.now() or new Date() directly in domain or service code.
Installation
npm install tsentials
Import
import { SystemDateTimeProvider, createFakeDateTimeProvider } from 'tsentials/time';
import type { DateTimeProvider } from 'tsentials/time';
DateTimeProvider Interface
interface DateTimeProvider {
utcNow(): Date;
utcNowDate(): Date;
utcNowMs(): number;
}
There is no now(), nowMs(), or today() method.
Production: SystemDateTimeProvider
SystemDateTimeProvider is a const object — not a class. Do not use new.
import { SystemDateTimeProvider } from 'tsentials/time';
const now: Date = SystemDateTimeProvider.utcNow();
const todayDate: Date = SystemDateTimeProvider.utcNowDate();
const ms: number = SystemDateTimeProvider.utcNowMs();
const timeProvider: DateTimeProvider = SystemDateTimeProvider;
Use in Services
class OrderService {
constructor(private readonly time: DateTimeProvider) {}
createOrder(cart: Cart): Order {
return {
id: crypto.randomUUID(),
createdAt: this.time.utcNow(),
expiresAt: new Date(this.time.utcNowMs() + 7 * 24 * 60 * 60 * 1000),
};
}
}
const service = new OrderService(SystemDateTimeProvider);
Testing: createFakeDateTimeProvider
Returns a DateTimeProvider with two extra methods: advance(ms) and setTime(date).
import { createFakeDateTimeProvider } from 'tsentials/time';
const fakeTime = createFakeDateTimeProvider(new Date('2025-01-15T10:00:00Z'));
const service = new OrderService(fakeTime);
const order = service.createOrder(cart);
expect(order.createdAt).toEqual(new Date('2025-01-15T10:00:00Z'));
fakeTime.advance(2 * 60 * 60 * 1000);
expect(fakeTime.utcNowMs()).toBe(new Date('2025-01-15T12:00:00Z').getTime());
expect(fakeTime.utcNow()).toEqual(new Date('2025-01-15T12:00:00Z'));
fakeTime.setTime(new Date('2025-06-01T00:00:00Z'));
expect(fakeTime.utcNow()).toEqual(new Date('2025-06-01T00:00:00Z'));
fakeTime.setTime(new Date('2025-03-15T14:30:00Z'));
expect(fakeTime.utcNowDate()).toEqual(new Date('2025-03-15T00:00:00Z'));
Complete API Reference
| Object/Function | Type | Description |
|---|
SystemDateTimeProvider | DateTimeProvider (const object) | Production implementation, delegates to system clock |
createFakeDateTimeProvider(fixed) | (Date) => DateTimeProvider & { advance, setTime } | Test double with fixed time |
| DateTimeProvider Method | Signature | Description |
|---|
utcNow() | () => Date | Current UTC time |
utcNowDate() | () => Date | Current UTC date (time zeroed) |
utcNowMs() | () => number | Current timestamp in ms |
| Fake-only Method | Signature | Description |
|---|
advance(ms) | (number) => void | Move clock forward by ms |
setTime(date) | (Date) => void | Set clock to exact time |
Best Practices
- Inject
DateTimeProvider — never call new Date() or Date.now() directly in domain/service code
SystemDateTimeProvider is a const object — use directly, do not instantiate with new
createFakeDateTimeProvider() is for tests — freeze time to make assertions deterministic
fakeTime.advance(ms) simulates elapsed time without setTimeout or sleep in tests
- Use
utcNow() for timestamps, utcNowDate() for date-only comparisons, utcNowMs() for numeric timestamps