chronos-ts
v2.0.1
Published
A comprehensive TypeScript library for date and time manipulation, inspired by Carbon PHP. Features immutable API, intervals, periods, timezones, and i18n support.
Maintainers
Readme
Chronos-ts ⏰
Chronos-ts — named after the Greek god of time — is a comprehensive TypeScript library for date and time manipulation. Version 2.0 is a complete rewrite inspired by Carbon PHP, bringing modern, intuitive date handling to TypeScript and JavaScript.
[!WARNING] This is a major rewrite (v2.0) and is not backward compatible with v1.x. Please refer to the migration guide for details.
✨ Features
- 🎯 Intuitive API — Fluent, chainable methods for all date operations
- 📅 Immutable by Default — All operations return new instances
- 🌍 Timezone Support — Built-in timezone handling with DST awareness
- 🌐 Internationalization — Extensible locale system with human-readable output
- ⏱️ Intervals — Powerful duration/interval handling (like CarbonInterval)
- 📆 Periods — Date range iteration with filtering and transformations
- 📋 Period Collections — Manage and analyze multiple date periods easily
- 📐 Type-Safe — Full TypeScript support with comprehensive types
- 🪶 Zero Dependencies — No external runtime dependencies
📦 Installation
npm install chronos-ts
# or
yarn add chronos-ts
# or
pnpm add chronos-ts🚀 Quick Start
import { Chronos, ChronosInterval, ChronosPeriod } from 'chronos-ts';
// Create dates
const now = Chronos.now();
const birthday = Chronos.create(1990, 6, 15);
const parsed = Chronos.parse('2024-03-15T10:30:00');
// Manipulate dates
const nextWeek = now.addWeeks(1);
const lastMonth = now.subtractMonths(1);
const startOfDay = now.startOf('day');
// Format dates
console.log(now.format('YYYY-MM-DD HH:mm:ss')); // "2024-03-15 14:30:45"
console.log(now.diffForHumans(birthday)); // "33 years ago"
// Work with intervals
const interval = ChronosInterval.create({ hours: 2, minutes: 30 });
console.log(interval.forHumans()); // "2 hours 30 minutes"
// Iterate over periods
const thisMonth = ChronosPeriod.thisMonth();
for (const day of thisMonth) {
console.log(day.format('YYYY-MM-DD'));
}📖 API Reference
For detailed documentation on all classes and methods, please refer to the API Reference.
Core Classes
- Chronos: The main class for date/time manipulation.
- ChronosInterval: Represents a duration of time.
- ChronosPeriod: Represents a date range or schedule.
- ChronosPeriodCollection: Manages collections of periods.
- ChronosTimezone: Timezone utilities.
🌍 Localization
Chronos-ts includes built-in support for English and Spanish, with an extensible locale system.
import { Chronos, registerLocale, getLocale } from 'chronos-ts';
// Use built-in locale
const date = Chronos.now().locale('es');
date.format('dddd, D [de] MMMM [de] YYYY');
// "viernes, 15 de marzo de 2024"
// Human-readable in Spanish
date.diffForHumans(Chronos.yesterday());
// "hace 1 día"
// Register custom locale
registerLocale({
code: 'de',
months: ['Januar', 'Februar', 'März', 'April', 'Mai', 'Juni',
'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember'],
monthsShort: ['Jan', 'Feb', 'Mär', 'Apr', 'Mai', 'Jun',
'Jul', 'Aug', 'Sep', 'Okt', 'Nov', 'Dez'],
weekdays: ['Sonntag', 'Montag', 'Dienstag', 'Mittwoch',
'Donnerstag', 'Freitag', 'Samstag'],
weekdaysShort: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
weekdaysMin: ['So', 'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa'],
relativeTime: {
future: 'in %s',
past: 'vor %s',
s: 'wenigen Sekunden',
ss: '%d Sekunden',
m: 'einer Minute',
mm: '%d Minuten',
h: 'einer Stunde',
hh: '%d Stunden',
d: 'einem Tag',
dd: '%d Tagen',
M: 'einem Monat',
MM: '%d Monaten',
y: 'einem Jahr',
yy: '%d Jahren',
},
});🔧 Configuration
import { Chronos } from 'chronos-ts';
// Set global configuration
Chronos.configure({
defaultTimezone: 'America/New_York',
defaultLocale: 'en',
});
// Set test/mock time (useful for testing)
Chronos.setTestNow(Chronos.create(2024, 1, 1));
const now = Chronos.now(); // Returns 2024-01-01
// Reset test time
Chronos.setTestNow(null);📚 Real-World Examples
Event Planning
import { Chronos, ChronosPeriod, ChronosInterval } from 'chronos-ts';
// Conference dates
const conference = {
start: Chronos.create(2024, 6, 15, 9, 0),
end: Chronos.create(2024, 6, 17, 18, 0),
};
// Check if a session conflicts
const session = Chronos.create(2024, 6, 16, 14, 0);
const isDuringConference = session.isBetween(conference.start, conference.end);
// Create weekly recurring meeting
const meetings = ChronosPeriod
.create(
Chronos.now(),
Chronos.now().addMonths(3),
{ weeks: 1 }
)
.filter(date => date.dayOfWeek === 1) // Mondays only
.toArray();Subscription Management
import { Chronos, ChronosInterval } from 'chronos-ts';
class Subscription {
constructor(
public startDate: Chronos,
public interval: ChronosInterval
) {}
get nextBillingDate(): Chronos {
return this.startDate.add(this.interval);
}
isActive(): boolean {
return Chronos.now().isBefore(this.nextBillingDate);
}
daysUntilRenewal(): number {
return this.nextBillingDate.diffInDays(Chronos.now());
}
}
const monthly = new Subscription(
Chronos.now(),
ChronosInterval.months(1)
);
console.log(`Days until renewal: ${monthly.daysUntilRenewal()}`);Work Schedule
import { Chronos, ChronosPeriod } from 'chronos-ts';
// Get working days this month
const workingDays = ChronosPeriod
.thisMonth()
.filterWeekdays()
.toArray();
console.log(`Working days this month: ${workingDays.length}`);
// Calculate hours worked
const clockIn = Chronos.create(2024, 3, 15, 9, 0);
const clockOut = Chronos.create(2024, 3, 15, 17, 30);
const hoursWorked = clockOut.diffInHours(clockIn);
const overtime = Math.max(0, hoursWorked - 8);
console.log(`Hours worked: ${hoursWorked}`);
console.log(`Overtime: ${overtime}`);Age Calculator
import { Chronos } from 'chronos-ts';
function getAge(birthDate: Chronos): { years: number; months: number; days: number } {
const now = Chronos.now();
return {
years: now.diffInYears(birthDate),
months: now.diffInMonths(birthDate) % 12,
days: now.diffInDays(birthDate.addYears(now.diffInYears(birthDate))) % 30,
};
}
const birthday = Chronos.create(1990, 6, 15);
const age = getAge(birthday);
console.log(`Age: ${age.years} years, ${age.months} months, ${age.days} days`);🧪 Testing
import { Chronos } from 'chronos-ts';
describe('MyFeature', () => {
beforeEach(() => {
// Freeze time for consistent tests
Chronos.setTestNow(Chronos.create(2024, 1, 15, 12, 0, 0));
});
afterEach(() => {
// Reset to real time
Chronos.setTestNow(null);
});
it('should calculate correct deadline', () => {
const deadline = Chronos.now().addDays(30);
expect(deadline.format('YYYY-MM-DD')).toBe('2024-02-14');
});
});🆚 Comparison with Other Libraries
| Feature | Chronos-ts | Day.js | Moment.js | date-fns | |---------|-----------|--------|-----------|----------| | Immutable | ✅ | ✅ | ❌ | ✅ | | TypeScript | ✅ Native | Plugin | Plugin | ✅ Native | | Tree-shakeable | ✅ | ✅ | ❌ | ✅ | | Intervals | ✅ | Plugin | ✅ | ❌ | | Periods | ✅ | ❌ | ❌ | ❌ | | Timezones | ✅ | Plugin | Plugin | ✅ | | Zero deps | ✅ | ✅ | ❌ | ✅ | | API Style | Fluent | Fluent | Fluent | Functional |
🤝 Contributing
Contributions, issues, and feature requests are welcome! See CONTRIBUTING.md for guidelines.
# Clone the repository
git clone https://github.com/hendurhance/chronos-ts.git
# Install dependencies
npm install
# Run tests
npm test
# Build
npm run build📄 License
This project is licensed under the MIT License — see the LICENSE file for details.
🙏 Acknowledgements
- Carbon PHP — Primary API inspiration
- Day.js — Immutability patterns
- Moment.js — Format string patterns
- Period - Complex period comparisons
Made with ❤️ by the Chronos-ts team
