{"_id":"24x7","name":"24x7","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"24x7","version":"1.0.0","description":"A production-ready date/time library for JavaScript with first-class intervals, business-aware date math, timezone support, and deterministic time control","type":"module","main":"src/index.js","exports":{".":{"import":"./src/index.js","require":"./src/index.js"}},"scripts":{"test":"node test/index.js"},"keywords":["date","time","datetime","timezone","calendar","interval","range","business-days","immutable","utc","iana-timezone","testing","date-ranges"],"author":{"name":"Venkatesh Gandham"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/venu9l/24x7.git"},"engines":{"node":">=14.0.0"},"_id":"24x7@1.0.0","gitHead":"3b4bbfbca420d0bd14162db73836da855a46ab7b","bugs":{"url":"https://github.com/venu9l/24x7/issues"},"homepage":"https://github.com/venu9l/24x7#readme","_nodeVersion":"20.14.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-qbgzmVx6D5uX0qinPmuwnLkG+YFZcTt/FWJeRT0c5U6ePc/40iB+/fmyvjJzYwK0zhf6bjryeewAp8SkEENKhg==","shasum":"fd3803040b96698fb4d5de2f09c6cd5855124b41","tarball":"https://registry.npmjs.org/24x7/-/24x7-1.0.0.tgz","fileCount":17,"unpackedSize":140322,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIBVn+8GPo9QPf5HJU4Bs1C8GeAUJRpAZJcUi5FZePClWAiBWF+uW0LCNueDH74tlnLAQe0Ke0BHgNdX6eQTULwWc3w=="}]},"_npmUser":{"name":"venu9l","email":"svj225@gmail.com"},"directories":{},"maintainers":[{"name":"venu9l","email":"svj225@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/24x7_1.0.0_1767963570119_0.5169332378463443"},"_hasShrinkwrap":false}},"time":{"created":"2026-01-09T12:59:30.118Z","1.0.0":"2026-01-09T12:59:30.278Z","modified":"2026-01-09T12:59:30.528Z"},"maintainers":[{"name":"venu9l","email":"svj225@gmail.com"}],"description":"A production-ready date/time library for JavaScript with first-class intervals, business-aware date math, timezone support, and deterministic time control","homepage":"https://github.com/venu9l/24x7#readme","keywords":["date","time","datetime","timezone","calendar","interval","range","business-days","immutable","utc","iana-timezone","testing","date-ranges"],"repository":{"type":"git","url":"git+https://github.com/venu9l/24x7.git"},"author":{"name":"Venkatesh Gandham"},"bugs":{"url":"https://github.com/venu9l/24x7/issues"},"license":"MIT","readme":"# 24x7\n\nA production-ready date/time library for JavaScript with unique features for modern applications.\n\n## Why 24x7 Exists\n\n24x7 was created to provide a modern, production-ready date/time library with unique features:\n\n1. **First-class intervals** - Work with time intervals as first-class objects with end-exclusive behavior\n2. **First-class date ranges** - Work with date ranges as first-class objects, not just calculations\n3. **Business-aware date math** - Handle business days, holidays, and custom weekends with ease\n4. **Deterministic time control** - Freeze time for predictable testing without global side effects\n5. **Timezone support** - Full timezone support with UTC default and IANA timezone support\n6. **Global configuration** - Set defaults for formats, weekends, holidays, and more\n7. **Flexible parsing** - Support for custom date formats with automatic ISO detection\n\n## Installation\n\n```bash\nnpm install 24x7\n```\n\n## Quick Start\n\n```javascript\nimport _tx from '24x7';\n\n// Create a date\nconst date = _tx('2025-01-15');\n\n// Chain operations (all immutable)\nconst nextWeek = date.addDays(7).startOfDay();\n\n// Format\nconsole.log(nextWeek.format('YYYY-MM-DD')); // '2025-01-22'\n```\n\n## Configuration\n\n24x7 supports comprehensive global configuration with a structured, hierarchical system. Configuration follows a priority system:\n\n1. **Instance overrides** (highest priority)\n2. **Global config** (set via `_tx.config()`)\n3. **DEFAULT_CONFIG** (lowest priority)\n\n### Basic Usage\n\n```javascript\nimport _tx from '24x7';\n\n// Get current configuration\nconst config = _tx.config();\n\n// Set configuration options\n_tx.config({\n  immutable: true,\n  parsing: {\n    inputFormats: ['DD/MM/YYYY', 'YYYY-MM-DD'],\n    strict: false,\n    safe: true\n  },\n  formatting: {\n    outputFormat: 'YYYY-MM-DD'\n  },\n  calendar: {\n    weekends: [0, 6],\n    holidays: ['2025-01-15']\n  }\n});\n\n// Reset to defaults\n_tx.resetConfig();\n```\n\n### Configuration Structure\n\n#### Immutability\n\n```javascript\n_tx.config({\n  immutable: true,          // Instances are immutable by default\n  mutableFallback: false    // Allow mutation only when explicitly enabled\n});\n```\n\n**Usage:**\n```javascript\n// Default: immutable (returns new instance)\nconst date1 = _tx('2025-01-15');\nconst date2 = date1.addDays(5); // date1 unchanged\n\n// Explicitly enable mutation\nconst date3 = _tx('2025-01-15').immutable(false);\ndate3.addDays(5); // date3 is mutated in place\n```\n\n#### Parsing Configuration\n\n```javascript\n_tx.config({\n  parsing: {\n    inputFormats: ['DD/MM/YYYY', 'YYYY-MM-DD'], // Priority order\n    strict: false,          // Reject invalid dates\n    safe: true,             // Do not throw on invalid input\n    overflow: 'reject',     // 'reject' | 'clamp'\n    yearPivot: 50,          // Two-digit year pivot (50 = 1950-2049)\n    monthNames: null,       // Custom month names\n    allowNative: true,      // Fallback to native Date parsing\n    trimInput: true         // Trim input strings\n  }\n});\n```\n\n**Examples:**\n```javascript\n// Use inputFormats for automatic parsing\n_tx.config({\n  parsing: {\n    inputFormats: ['DD/MM/YYYY', 'MM/DD/YYYY']\n  }\n});\n\nx('23/01/2025'); // Parsed as DD/MM/YYYY\nx('01/23/2025'); // Parsed as MM/DD/YYYY\n\n// Strict mode rejects invalid dates\n_tx.config({\n  parsing: {\n    strict: true\n  }\n});\n\n// Safe mode returns current date instead of throwing\n_tx.config({\n  parsing: {\n    safe: true\n  }\n});\nx('invalid'); // Returns current date instead of throwing\n```\n\n#### Formatting Configuration\n\n```javascript\n_tx.config({\n  formatting: {\n    outputFormat: 'YYYY-MM-DD',\n    \n    tokens: {},             // Custom format tokens\n    \n    ordinal: n => `${n}th`, // Custom ordinal function\n    \n    pad: {\n      year: 4,\n      month: 2,\n      day: 2,\n      hour: 2,\n      minute: 2,\n      second: 2\n    },\n    \n    rules: {\n      sameDay: 'HH:mm',     // Format for same day\n      sameYear: 'MMM D',    // Format for same year\n      default: 'YYYY-MM-DD' // Default format\n    }\n  }\n});\n```\n\n**Examples:**\n```javascript\n// Set default output format\n_tx.config({\n  formatting: {\n    outputFormat: 'MMMM D, YYYY'\n  }\n});\n\nx('2025-01-15').format(); // \"January 15, 2025\"\n\n// Custom tokens\n_tx.config({\n  formatting: {\n    tokens: {\n      'Q': (date) => Math.floor(date.month() / 3) + 1\n    }\n  }\n});\n\nx('2025-01-15').format('YYYY-Q'); // \"2025-1\"\n```\n\n#### Calendar / Business Logic\n\n```javascript\n_tx.config({\n  calendar: {\n    weekends: [0, 6],       // Sunday, Saturday\n    weekStart: 1,           // Monday (0=Sunday, 1=Monday, etc.)\n    holidays: ['2025-01-15', '2025-12-25'], // ISO date strings\n    \n    businessHours: {\n      start: '09:00',\n      end: '17:00'\n    },\n    \n    includeHolidaysInRanges: false\n  }\n});\n```\n\n**Examples:**\n```javascript\n// Set global weekends and holidays\n_tx.config({\n  calendar: {\n    weekends: [0, 6],\n    holidays: ['2025-01-15', '2025-12-25']\n  }\n});\n\n// Business day methods use config defaults\nx('2025-01-10').addBusinessDays(5); // Uses config weekends/holidays\n\n// Override per call\nx('2025-01-10').addBusinessDays(5, {\n  weekends: [5, 6], // Override config\n  holidays: ['2025-01-20'] // Override config\n});\n```\n\n#### Date Math Configuration\n\n```javascript\n_tx.config({\n  math: {\n    clampMode: 'end',       // 'end' | 'strict' | 'overflow'\n    diffRounding: 'floor'   // 'floor' | 'ceil' | 'round'\n  }\n});\n```\n\n#### Time / Clock Control\n\n```javascript\n_tx.config({\n  time: {\n    timezone: 'UTC',        // 'UTC' | 'local' | IANA timezone (e.g., 'America/New_York')\n    precision: 'ms',        // 'ms' | 's'\n    freeze: false,          // false | Date | ISO string\n    dst: 'preserve',        // 'preserve' | 'shift' | 'error'\n    startOfDay: '00:00'\n  }\n});\n```\n\n**Examples:**\n```javascript\n// Set default timezone to UTC (default)\n_tx.config({\n  time: {\n    timezone: 'UTC'\n  }\n});\n\n// Set default timezone to local\n_tx.config({\n  time: {\n    timezone: 'local'\n  }\n});\n\n// Set default timezone to IANA timezone\n_tx.config({\n  time: {\n    timezone: 'America/New_York'\n  }\n});\n\n// Freeze time\n_tx.config({\n  time: {\n    freeze: '2025-01-15' // Freeze to specific date\n  }\n});\n\n// Or use the convenience method\n_tx.freeze('2025-01-15');\n```\n\n#### Debugging Configuration\n\n```javascript\n_tx.config({\n  debug: {\n    warnings: false,\n    onWarn: (message, context) => {\n      console.warn(message, context);\n    }\n  }\n});\n```\n\n#### Performance Configuration\n\n```javascript\n_tx.config({\n  performance: {\n    cacheFormats: true,     // Cache compiled format patterns\n    fastParse: false        // Use faster but less strict parsing\n  }\n});\n```\n\n#### Policy / Guards\n\n```javascript\n_tx.config({\n  policy: {\n    maxFuture: '2y',        // Maximum future date (e.g., '2y', '1M')\n    maxPast: '10y',         // Maximum past date\n    forbidWeekends: false,  // Reject weekend dates\n    forbidHolidays: false   // Reject holiday dates\n  }\n});\n```\n\n#### Intervals / Ranges Configuration\n\n```javascript\n_tx.config({\n  intervals: {\n    inclusive: false,       // End-exclusive by default\n    allowZeroDuration: false,\n    splitRemainder: true,   // Keep leftover when splitting\n    defaultSplitUnit: 'minute',\n    overlap: {\n      inclusive: false      // End === start is NOT overlap\n    },\n    businessOnly: false     // Ignore non-business time by default\n  }\n});\n```\n\n**Examples:**\n```javascript\n// End-exclusive intervals (default)\n_tx.config({\n  intervals: {\n    inclusive: false\n  }\n});\nconst interval = _tx('2025-01-01').interval('2025-01-10');\ninterval.contains('2025-01-10'); // false (end-exclusive)\n\n// End-inclusive intervals\n_tx.config({\n  intervals: {\n    inclusive: true\n  }\n});\nconst inclusiveInterval =_tx('2025-01-01').interval('2025-01-10');\ninclusiveInterval.contains('2025-01-10'); // true (end-inclusive)\n\n// Allow zero-duration intervals\n_tx.config({\n  intervals: {\n    allowZeroDuration: true\n  }\n});\nconst zeroInterval =_tx('2025-01-01').interval('2025-01-01'); // Allowed\n```\n\n### Instance-Level Configuration\n\nYou can override configuration per instance:\n\n```javascript\n// Create instance with custom config\nconst date =_tx('2025-01-15', {\n  immutable: false,\n  calendar: {\n    weekends: [5, 6] // Friday-Saturday weekend\n  }\n});\n\n// Or modify immutability after creation\nconst mutableDate =_tx('2025-01-15').immutable(false);\nmutableDate.addDays(5); // Mutates in place\n```\n\n### Configuration Resolution\n\nConfiguration is resolved with the following priority:\n\n1. **Instance overrides** - Passed when creating DateTime or via `.immutable()`\n2. **Global config** - Set via `_tx.config()`\n3. **DEFAULT_CONFIG** - Built-in defaults\n\n```javascript\n// Global config\n_tx.config({\n  calendar: {\n    weekends: [0, 6]\n  }\n});\n\n// Instance override\nconst date =_tx('2025-01-15', {\n  calendar: {\n    weekends: [5, 6] // This instance uses Friday-Saturday\n  }\n});\n\n// Method-level override (highest priority)\ndate.addBusinessDays(5, {\n  weekends: [1, 2] // This call uses Monday-Tuesday\n});\n```\n\n## Core Features\n\n### Immutable API (Default)\n\nBy default, all operations return new instances. The original date is never modified:\n\n```javascript\nconst date1 =_tx('2025-01-15');\nconst date2 = date1.addDays(5);\n\nconsole.log(date1.format('YYYY-MM-DD')); // '2025-01-15' (unchanged)\nconsole.log(date2.format('YYYY-MM-DD')); // '2025-01-20'\n```\n\n### Mutable Mode (Explicit)\n\nYou can enable mutation for specific instances:\n\n```javascript\n// Enable mutation explicitly\nconst date =_tx('2025-01-15').immutable(false);\ndate.addDays(5); // Mutates date in place\n\n// Check immutability\ndate.isImmutable(); // false\n\n// Create mutable instance from config\nconst mutableDate =_tx('2025-01-15', { immutable: false });\nmutableDate.addDays(5); // Mutates in place\n```\n\n**Note:** Immutability is the default and recommended mode. Use mutable mode only when explicitly needed for performance or specific use cases.\n\n### Chainable Methods\n\nMethods can be chained for fluent APIs:\n\n```javascript\nconst result =_tx('2025-01-15')\n  .addMonths(1)\n  .startOfMonth()\n  .addDays(2)\n  .format('YYYY-MM-DD');\n```\n\n## Unique Features\n\n### 1️⃣ Intervals (First-class)\n\nWork with time intervals as first-class objects with end-exclusive behavior by default:\n\n#### Creating Intervals\n\n```javascript\nimport _tx from '24x7';\n\n// Create an interval (end-exclusive by default)\nconst interval =_tx('2025-01-01').interval('2025-01-10');\n\n// Static method (alternative)\nconst staticInterval = _tx.interval('2025-01-01', '2025-01-10');\n\n// End-exclusive: [start, end) - end is NOT included\nconst exclusive =_tx('2025-01-01').interval('2025-01-10');\nexclusive.contains('2025-01-01'); // true\nexclusive.contains('2025-01-10'); // false (end is exclusive)\n```\n\n#### Interval Configuration\n\n```javascript\n_tx.config({\n  intervals: {\n    inclusive: false,       // End-exclusive by default\n    allowZeroDuration: false,\n    splitRemainder: true,   // Keep leftover when splitting\n    defaultSplitUnit: 'minute',\n    overlap: {\n      inclusive: false      // End === start is NOT overlap\n    },\n    businessOnly: false     // Ignore non-business time by default\n  }\n});\n```\n\n#### Checking if Date or Interval is Contained\n\n```javascript\nimport _tx from '24x7';\n\nconst interval =_tx('2025-01-01').interval('2025-01-10');\n\n// Check if date is in interval\ninterval.contains('2025-01-05'); // true\ninterval.contains('2025-01-10'); // false (end-exclusive)\n\n// Check if another interval is contained\nconst large =_tx('2025-01-01').interval('2025-01-31');\nconst small =_tx('2025-01-10').interval('2025-01-20');\nlarge.contains(small); // true\n```\n\n#### Overlap Detection\n\n```javascript\nimport _tx from '24x7';\n\nconst interval1 =_tx('2025-01-01').interval('2025-01-10');\nconst interval2 =_tx('2025-01-05').interval('2025-01-15');\nconst interval3 =_tx('2025-01-20').interval('2025-01-25');\n\ninterval1.overlaps(interval2); // true\ninterval1.overlaps(interval3); // false\n\n// With inclusive overlap option\ninterval1.overlaps(interval2, { inclusive: true });\n```\n\n#### Intersection\n\n```javascript\nimport _tx from '24x7';\n\nconst interval1 =_tx('2025-01-01').interval('2025-01-10');\nconst interval2 =_tx('2025-01-05').interval('2025-01-15');\n\nconst intersection = interval1.intersect(interval2);\nif (intersection) {\n  console.log(intersection.start().format('YYYY-MM-DD')); // '2025-01-05'\n  console.log(intersection.end().format('YYYY-MM-DD'));   // '2025-01-10'\n}\n```\n\n#### Clamping\n\n```javascript\nimport _tx from '24x7';\n\nconst container =_tx('2025-01-01').interval('2025-01-31');\nconst toClamp =_tx('2024-12-25').interval('2025-02-05');\n\nconst clamped = container.clamp(toClamp);\n// Clamped to fit within container: 2025-01-01 to 2025-01-31\n```\n\n#### Splitting Intervals\n\n```javascript\nimport _tx from '24x7';\n\nconst interval =_tx('2025-01-01T00:00:00').interval('2025-01-01T02:30:00');\n\n// Split by unit\nconst hourIntervals = interval.splitBy('hour');\n// Returns array of 1-hour intervals\n\n// Split by duration (milliseconds)\nconst customIntervals = interval.splitBy(30 * 60 * 1000); // 30 minutes\n```\n\n#### Iterating Over Intervals\n\n```javascript\nimport _tx from '24x7';\n\nconst interval =_tx('2025-01-01').interval('2025-01-05');\n\n// Iterate by day\nfor (const day of interval.iterate('day')) {\n  console.log(day.format('YYYY-MM-DD'));\n}\n// Output:\n// 2025-01-01\n// 2025-01-02\n// 2025-01-03\n// 2025-01-04\n// (2025-01-05 is excluded - end-exclusive)\n```\n\n#### Duration Calculations\n\n```javascript\nimport _tx from '24x7';\n\nconst interval =_tx('2025-01-01T10:00:00').interval('2025-01-01T14:30:00');\n\ninterval.duration();        // Duration in milliseconds (default)\ninterval.duration('s');     // Duration in seconds\ninterval.duration('minute'); // Duration in minutes\ninterval.duration('hour');  // Duration in hours\ninterval.duration('day');   // Duration in days\n```\n\n#### Merging Intervals\n\n```javascript\nimport _tx from '24x7';\n\nconst interval1 =_tx('2025-01-01').interval('2025-01-10');\nconst interval2 =_tx('2025-01-05').interval('2025-01-15');\nconst interval3 =_tx('2025-01-20').interval('2025-01-25');\n\nconst merged = _tx.merge([interval1, interval2, interval3]);\n// Returns interval from earliest start to latest end\n// 2025-01-01 to 2025-01-25\n```\n\n#### Real-World Use Cases\n\n```javascript\nimport _tx from '24x7';\n\n// Use case 1: Time slot booking\nfunction isTimeSlotAvailable(slot, bookedSlots) {\n  return !bookedSlots.some(booked => slot.overlaps(booked));\n}\n\n// Use case 2: Calculate working hours in interval\nfunction getWorkingHours(interval, businessHours) {\n  // Filter to business hours only\n  return interval.splitBy('hour').filter(hour => {\n    const hourStart = hour.start().hour();\n    return hourStart >= 9 && hourStart < 17;\n  });\n}\n\n// Use case 3: Find gaps between intervals\nfunction findGaps(intervals) {\n  // Sort by start time\n  const sorted = [...intervals].sort((a, b) => \n    a.start().getTime() - b.start().getTime()\n  );\n  \n  const gaps = [];\n  for (let i = 0; i < sorted.length - 1; i++) {\n    const gap = sorted[i].end().interval(sorted[i + 1].start());\n    if (gap.duration() > 0) {\n      gaps.push(gap);\n    }\n  }\n  return gaps;\n}\n```\n\n### 2️⃣ Date Ranges (First-class)\n\nWork with date ranges as first-class objects:\n\n#### Creating Ranges\n\n```javascript\nimport _tx from '24x7';\n\n// Create a range from a date to another date\nconst range =_tx('2025-01-01').range('2025-01-10');\n\n// Static method (alternative)\nconst staticRange = _tx.range('2025-01-01', '2025-01-10');\n\n// Range with different input types\nconst range2 =_tx('2025-01-01').range(new Date('2025-01-10'));\nconst range3 =_tx(new Date('2025-01-01')).range('2025-01-10');\n\n// Single day range\nconst singleDay =_tx('2025-01-15').range('2025-01-15');\n```\n\n#### Checking if Date is in Range\n\n```javascript\nimport _tx from '24x7';\n\nconst range =_tx('2025-01-01').range('2025-01-10');\n\n// Check with DateTime instance\nrange.contains(_tx('2025-01-05')); // true\nrange.contains(_tx('2025-01-15')); // false\n\n// Check with string\nrange.contains('2025-01-05'); // true\nrange.contains('2025-01-01'); // true (inclusive start)\nrange.contains('2025-01-10'); // true (inclusive end)\n\n// Check with Date object\nrange.contains(new Date('2025-01-05')); // true\n\n// Real-world example: Check if today is in a promotion period\nconst promotionStart =_tx('2025-01-01');\nconst promotionEnd =_tx('2025-01-31');\nconst promotionRange = promotionStart.range(promotionEnd);\nconst isPromotionActive = promotionRange.contains(_tx()); // true if today is in range\n```\n\n#### Getting Range Information\n\n```javascript\nimport _tx from '24x7';\n\nconst range =_tx('2025-01-01').range('2025-01-10');\n\n// Get start and end dates\nconst start = range.start(); // DateTime instance\nconst end = range.end();     // DateTime instance\n\nconsole.log(start.format('YYYY-MM-DD')); // '2025-01-01'\nconsole.log(end.format('YYYY-MM-DD'));   // '2025-01-10'\n\n// Get number of days (inclusive)\nrange.days(); // 10 (includes both start and end)\n\n// Calculate duration in other units\nconst days = range.days();\nconst hours = days * 24;\nconst minutes = hours * 60;\n```\n\n#### Iterating Over Range\n\n```javascript\nimport _tx from '24x7';\n\nconst range =_tx('2025-01-01').range('2025-01-05');\n\n// Iterate with for...of\nfor (const day of range) {\n  console.log(day.format('YYYY-MM-DD'));\n}\n// Output:\n// 2025-01-01\n// 2025-01-02\n// 2025-01-03\n// 2025-01-04\n// 2025-01-05\n\n// Convert to array\nconst daysArray = range.toArray();\nconsole.log(daysArray.length); // 5\n\n// Use array methods\nconst weekdays = range.toArray().filter(day => {\n  const dayOfWeek = day.day();\n  return dayOfWeek !== 0 && dayOfWeek !== 6; // Exclude weekends\n});\n\n// Map to formatted strings\nconst formattedDays = range.toArray().map(day => day.format('MMM D'));\nconsole.log(formattedDays); // ['Jan 1', 'Jan 2', 'Jan 3', 'Jan 4', 'Jan 5']\n\n// Real-world example: Get all business days in a range\nconst businessDays = range.toArray().filter(day => {\n  return day.isBusinessDay({ weekends: [0, 6] });\n});\n```\n\n#### Range Overlap Detection\n\n```javascript\nimport _tx from '24x7';\n\nconst range1 =_tx('2025-01-01').range('2025-01-10');\nconst range2 =_tx('2025-01-05').range('2025-01-15');\nconst range3 =_tx('2025-01-20').range('2025-01-25');\n\n// Check if ranges overlap\nrange1.overlaps(range2); // true (overlaps from Jan 5-10)\nrange1.overlaps(range3); // false (no overlap)\n\n// Real-world example: Check if booking periods conflict\nconst booking1 =_tx('2025-01-10').range('2025-01-15');\nconst booking2 =_tx('2025-01-12').range('2025-01-18');\nconst hasConflict = booking1.overlaps(booking2); // true\n\n// Find overlapping period\nif (booking1.overlaps(booking2)) {\n  const overlapStart = booking1.start().isAfter(booking2.start()) \n    ? booking1.start() \n    : booking2.start();\n  const overlapEnd = booking1.end().isBefore(booking2.end()) \n    ? booking1.end() \n    : booking2.end();\n  const overlapRange = overlapStart.range(overlapEnd);\n  console.log(`Overlap: ${overlapRange.days()} days`);\n}\n```\n\n#### Real-World Use Cases\n\n```javascript\nimport _tx from '24x7';\n\n// Use case 1: Event date range validation\nfunction isEventDateValid(eventStart, eventEnd, today = _tx()) {\n  const eventRange = eventStart.range(eventEnd);\n  return eventRange.contains(today) || eventRange.start().isAfter(today);\n}\n\n// Use case 2: Calculate working days in a project timeline\nfunction getWorkingDays(startDate, endDate, holidays = []) {\n  const range =_tx(startDate).range(endDate);\n  return range.toArray().filter(day => {\n    return day.isBusinessDay({ weekends: [0, 6], holidays });\n  }).length;\n}\n\n// Use case 3: Check if two schedules conflict\nfunction schedulesConflict(schedule1Start, schedule1End, schedule2Start, schedule2End) {\n  const schedule1 =_tx(schedule1Start).range(schedule1End);\n  const schedule2 =_tx(schedule2Start).range(schedule2End);\n  return schedule1.overlaps(schedule2);\n}\n```\n\n### 3️⃣ Business-Aware Date Math\n\nHandle business days with custom weekends and holidays:\n\n#### Adding Business Days\n\n```javascript\nimport _tx from '24x7';\n\n// Basic usage: Add 5 business days (skips weekends)\nconst result =_tx('2025-01-10') // Friday\n  .addBusinessDays(5, {\n    weekends: [0, 6] // Sunday and Saturday\n  });\n// Result: 2025-01-17 (Friday) - skips weekend\n\n// With holidays\nconst result2 =_tx('2025-01-10')\n  .addBusinessDays(5, {\n    weekends: [0, 6],\n    holidays: ['2025-01-15', '2025-01-20'] // Wednesday and Monday\n  });\n// Skips weekends AND holidays\n\n// Custom weekends (e.g., Friday-Saturday weekend)\nconst result3 =_tx('2025-01-08') // Wednesday\n  .addBusinessDays(3, {\n    weekends: [5, 6] // Friday and Saturday\n  });\n\n// Real-world example: Calculate delivery date (5 business days)\nconst orderDate =_tx('2025-01-10');\nconst holidays = ['2025-01-15', '2025-01-20']; // Company holidays\nconst deliveryDate = orderDate.addBusinessDays(5, {\n  weekends: [0, 6],\n  holidays\n});\nconsole.log(`Order placed: ${orderDate.format('MMM D')}`);\nconsole.log(`Expected delivery: ${deliveryDate.format('MMM D')}`);\n```\n\n#### Subtracting Business Days\n\n```javascript\nimport _tx from '24x7';\n\n// Subtract business days\nconst past =_tx('2025-01-20')\n  .subtractBusinessDays(3, {\n    weekends: [0, 6]\n  });\n\n// Real-world example: Calculate deadline (10 business days ago)\nconst deadline =_tx('2025-01-31')\n  .subtractBusinessDays(10, {\n    weekends: [0, 6],\n    holidays: ['2025-01-15']\n  });\nconsole.log(`Deadline: ${deadline.format('MMM D')}`);\n```\n\n#### Checking Business Days\n\n```javascript\nimport _tx from '24x7';\n\n// Check if a date is a business day\nx('2025-01-15').isBusinessDay({\n  weekends: [0, 6],\n  holidays: ['2025-01-15']\n}); // false (it's a holiday)\n\nx('2025-01-16').isBusinessDay({\n  weekends: [0, 6],\n  holidays: ['2025-01-15']\n}); // true (Thursday, not a holiday)\n\nx('2025-01-18').isBusinessDay({\n  weekends: [0, 6]\n}); // false (Saturday)\n\n// Real-world example: Validate business day\nfunction canProcessOrder(date, holidays = []) {\n  return _tx(date).isBusinessDay({\n    weekends: [0, 6],\n    holidays\n  });\n}\n\nif (canProcessOrder('2025-01-15', ['2025-01-15'])) {\n  console.log('Order can be processed today');\n} else {\n  console.log('Order will be processed next business day');\n}\n```\n\n#### Counting Business Days Between Dates\n\n```javascript\nimport _tx from '24x7';\n\n// Count business days between two dates\nconst count =_tx('2025-01-01')\n  .businessDaysUntil('2025-01-31', {\n    weekends: [0, 6],\n    holidays: ['2025-01-15']\n  });\n// Returns 21 (excluding weekends and holidays)\n\n// Forward count (positive)\nx('2025-01-10').businessDaysUntil('2025-01-20', {\n  weekends: [0, 6]\n}); // 7 business days\n\n// Backward count (negative)\nx('2025-01-20').businessDaysUntil('2025-01-10', {\n  weekends: [0, 6]\n}); // -7 business days\n\n// Real-world example: Calculate SLA remaining days\nfunction getSLARemainingDays(startDate, endDate, holidays = []) {\n  const today = _tx();\n  const remaining = today.businessDaysUntil(endDate, {\n    weekends: [0, 6],\n    holidays\n  });\n  return Math.max(0, remaining); // Don't return negative\n}\n\nconst startDate =_tx('2025-01-01');\nconst endDate =_tx('2025-01-31');\nconst remaining = getSLARemainingDays(startDate, endDate, ['2025-01-15']);\nconsole.log(`${remaining} business days remaining`);\n```\n\n#### Custom Weekend Configurations\n\n```javascript\nimport _tx from '24x7';\n\n// Middle Eastern weekend (Friday-Saturday)\nconst result =_tx('2025-01-08') // Wednesday\n  .addBusinessDays(3, {\n    weekends: [5, 6] // Friday and Saturday\n  });\n\n// No weekends (7-day work week)\nconst result2 =_tx('2025-01-10')\n  .addBusinessDays(5, {\n    weekends: [] // No weekends\n  });\n\n// Single day weekend\nconst result3 =_tx('2025-01-10')\n  .addBusinessDays(5, {\n    weekends: [0] // Only Sunday\n  });\n```\n\n#### Holiday Management\n\n```javascript\nimport _tx from '24x7';\n\n// Holidays as strings (ISO format preferred)\nconst holidays = [\n  '2025-01-01', // New Year\n  '2025-01-15', // Custom holiday\n  '2025-12-25'  // Christmas\n];\n\n// Holidays as Date objects\nconst holidayDates = [\n  new Date('2025-01-01'),\n  new Date('2025-01-15'),\n  new Date('2025-12-25')\n];\n\n// Holidays as DateTime instances\nconst holidayDateTimes = [\n_tx('2025-01-01'),\n_tx('2025-01-15'),\n_tx('2025-12-25')\n];\n\n// All work the same\nconst result = _tx('2025-01-10')\n  .addBusinessDays(5, {\n    weekends: [0, 6],\n    holidays: holidays // or holidayDates or holidayDateTimes\n  });\n\n// Real-world example: Company holiday calendar\nclass HolidayCalendar {\n  constructor() {\n    this.holidays = [];\n  }\n\n  addHoliday(date) {\n    this.holidays.push(_tx(date).format('YYYY-MM-DD'));\n    return this;\n  }\n\n  getBusinessDays(startDate, endDate) {\n    return _tx(startDate).businessDaysUntil(endDate, {\n      weekends: [0, 6],\n      holidays: this.holidays\n    });\n  }\n}\n\nconst calendar = new HolidayCalendar();\ncalendar\n  .addHoliday('2025-01-01')\n  .addHoliday('2025-07-04')\n  .addHoliday('2025-12-25');\n\nconst businessDays = calendar.getBusinessDays('2025-01-01', '2025-01-31');\nconsole.log(`${businessDays} business days in January`);\n```\n\n#### Real-World Use Cases\n\n```javascript\nimport _tx from '24x7';\n\n// Use case 1: Calculate invoice due date (Net 30 business days)\nfunction getInvoiceDueDate(invoiceDate, holidays = []) {\n  return _tx(invoiceDate).addBusinessDays(30, {\n    weekends: [0, 6],\n    holidays\n  });\n}\n\n// Use case 2: Project timeline with business days only\nfunction calculateProjectEndDate(startDate, businessDaysNeeded, holidays = []) {\n  return _tx(startDate).addBusinessDays(businessDaysNeeded, {\n    weekends: [0, 6],\n    holidays\n  });\n}\n\n// Use case 3: SLA monitoring\nfunction checkSLACompliance(createdDate, slaBusinessDays, holidays = []) {\n  const today = _tx();\n  const deadline =_tx(createdDate).addBusinessDays(slaBusinessDays, {\n    weekends: [0, 6],\n    holidays\n  });\n  \n  return {\n    deadline: deadline.format('YYYY-MM-DD'),\n    isOverdue: today.isAfter(deadline),\n    daysRemaining: today.businessDaysUntil(deadline, {\n      weekends: [0, 6],\n      holidays\n    })\n  };\n}\n\n// Use case 4: Work schedule validation\nfunction isValidWorkSchedule(startDate, endDate, maxConsecutiveDays, holidays = []) {\n  const range =_tx(startDate).range(endDate);\n  const businessDays = range.toArray().filter(day => \n    day.isBusinessDay({ weekends: [0, 6], holidays })\n  );\n  \n  // Check for consecutive days exceeding limit\n  let consecutive = 1;\n  let maxConsecutive = 1;\n  \n  for (let i = 1; i < businessDays.length; i++) {\n    const daysDiff = businessDays[i].getTime() - businessDays[i-1].getTime();\n    if (daysDiff === 24 * 60 * 60 * 1000) { // Exactly 1 day\n      consecutive++;\n      maxConsecutive = Math.max(maxConsecutive, consecutive);\n    } else {\n      consecutive = 1;\n    }\n  }\n  \n  return maxConsecutive <= maxConsecutiveDays;\n}\n```\n\n### 4️⃣ Deterministic Time Control (Testing-Friendly)\n\nFreeze time for predictable tests:\n\n#### Basic Freeze/Unfreeze\n\n```javascript\nimport _tx from '24x7';\n\n// Freeze time to a specific date\n_tx.freeze('2025-01-15');\n\n// Now _tx() always returns the frozen time\nconst now = _tx(); // Always '2025-01-15'\nconst later = _tx().addDays(1); // Always '2025-01-16'\n\n// Unfreeze to return to normal behavior\n_tx.unfreeze();\n\n// Check if time is frozen\n_tx.isFrozen(); // false\n```\n\n#### Freezing with Different Input Types\n\n```javascript\nimport _tx from '24x7';\n\n// Freeze with string\n_tx.freeze('2025-01-15');\n\n// Freeze with Date object\n_tx.freeze(new Date('2025-01-15'));\n\n// Freeze with timestamp\n_tx.freeze(1705334400000);\n\n// Freeze to current time (useful for snapshot testing)\n_tx.freeze(); // Freezes to current moment\n```\n\n#### Testing Examples\n\n```javascript\nimport _tx from '24x7';\n\n// Example 1: Testing date-dependent logic\ndescribe('Order Processing', () => {\n  beforeEach(() => {\n    // Freeze time to a known date\n    _tx.freeze('2025-01-15T10:00:00');\n  });\n\n  afterEach(() => {\n    // Always unfreeze in teardown\n    _tx.unfreeze();\n  });\n\n  it('should calculate delivery date correctly', () => {\n    const orderDate = _tx(); // Always '2025-01-15'\n    const deliveryDate = orderDate.addBusinessDays(5, {\n      weekends: [0, 6]\n    });\n    \n    expect(deliveryDate.format('YYYY-MM-DD')).toBe('2025-01-22');\n  });\n\n  it('should handle same-day orders', () => {\n    const orderDate = _tx();\n    const isSameDay = orderDate.format('YYYY-MM-DD') === _tx().format('YYYY-MM-DD');\n    expect(isSameDay).toBe(true);\n  });\n});\n\n// Example 2: Testing time-sensitive features\ndescribe('Promotion System', () => {\n  beforeEach(() => {\n    _tx.freeze('2025-01-10');\n  });\n\n  afterEach(() => {\n    _tx.unfreeze();\n  });\n\n  it('should check if promotion is active', () => {\n    const promotionStart =_tx('2025-01-01');\n    const promotionEnd =_tx('2025-01-31');\n    const range = promotionStart.range(promotionEnd);\n    \n    expect(range.contains(_tx())).toBe(true); // Today is in range\n  });\n\n  it('should detect expired promotions', () => {\n    _tx.freeze('2025-02-01'); // After promotion ends\n    \n    const promotionStart =_tx('2025-01-01');\n    const promotionEnd =_tx('2025-01-31');\n    const range = promotionStart.range(promotionEnd);\n    \n    expect(range.contains(_tx())).toBe(false); // Today is not in range\n  });\n});\n\n// Example 3: Testing with multiple freeze points\ndescribe('Time Progression', () => {\n  afterEach(() => {\n    _tx.unfreeze();\n  });\n\n  it('should simulate time progression', () => {\n    // Start at day 1\n    _tx.freeze('2025-01-01');\n    const day1 = _tx();\n    expect(day1.format('YYYY-MM-DD')).toBe('2025-01-01');\n\n    // Move to day 2\n    _tx.freeze('2025-01-02');\n    const day2 = _tx();\n    expect(day2.format('YYYY-MM-DD')).toBe('2025-01-02');\n\n    // Move to day 3\n    _tx.freeze('2025-01-03');\n    const day3 = _tx();\n    expect(day3.format('YYYY-MM-DD')).toBe('2025-01-03');\n  });\n});\n```\n\n#### Integration with Test Frameworks\n\n```javascript\nimport _tx from '24x7';\n\n// Jest example\ndescribe('My Feature', () => {\n  beforeAll(() => {\n    _tx.freeze('2025-01-15');\n  });\n\n  afterAll(() => {\n    _tx.unfreeze();\n  });\n\n  test('feature works with frozen time', () => {\n    // Your test code\n  });\n});\n\n// Mocha example\ndescribe('My Feature', function() {\n  beforeEach(function() {\n    _tx.freeze('2025-01-15');\n  });\n\n  afterEach(function() {\n    _tx.unfreeze();\n  });\n\n  it('should work with frozen time', function() {\n    // Your test code\n  });\n});\n\n// Vitest example\nimport { beforeEach, afterEach, test } from 'vitest';\n\nbeforeEach(() => {\n  _tx.freeze('2025-01-15');\n});\n\nafterEach(() => {\n  _tx.unfreeze();\n});\n\ntest('feature works', () => {\n  // Your test code\n});\n```\n\n#### Real-World Testing Scenarios\n\n```javascript\nimport _tx from '24x7';\n\n// Scenario 1: Testing subscription renewal\ndescribe('Subscription Service', () => {\n  beforeEach(() => {\n    _tx.freeze('2025-01-15');\n  });\n\n  afterEach(() => {\n    _tx.unfreeze();\n  });\n\n  it('should calculate next billing date', () => {\n    const subscriptionDate =_tx('2025-01-01');\n    const nextBilling = subscriptionDate.addMonths(1);\n    \n    expect(nextBilling.format('YYYY-MM-DD')).toBe('2025-02-01');\n  });\n\n  it('should detect expired subscriptions', () => {\n    const expiryDate =_tx('2025-01-10');\n    const isExpired = _tx().isAfter(expiryDate);\n    \n    expect(isExpired).toBe(true); // Today is after expiry\n  });\n});\n\n// Scenario 2: Testing business day calculations\ndescribe('Business Day Calculator', () => {\n  beforeEach(() => {\n    _tx.freeze('2025-01-15'); // Wednesday\n  });\n\n  afterEach(() => {\n    _tx.unfreeze();\n  });\n\n  it('should skip weekends', () => {\n    const start =_tx('2025-01-15'); // Wednesday\n    const result = start.addBusinessDays(2, { weekends: [0, 6] });\n    \n    // Should be Friday (skips weekend if it falls on one)\n    expect(result.format('YYYY-MM-DD')).toBe('2025-01-17');\n  });\n\n  it('should skip holidays', () => {\n    const start =_tx('2025-01-14'); // Tuesday\n    const result = start.addBusinessDays(1, {\n      weekends: [0, 6],\n      holidays: ['2025-01-15'] // Wednesday is a holiday\n    });\n    \n    // Should skip to Thursday\n    expect(result.format('YYYY-MM-DD')).toBe('2025-01-16');\n  });\n});\n\n// Scenario 3: Testing date range operations\ndescribe('Date Range Operations', () => {\n  beforeEach(() => {\n    _tx.freeze('2025-01-15');\n  });\n\n  afterEach(() => {\n    _tx.unfreeze();\n  });\n\n  it('should check if current date is in range', () => {\n    const range =_tx('2025-01-01').range('2025-01-31');\n    expect(range.contains(_tx())).toBe(true);\n  });\n\n  it('should handle edge cases', () => {\n    const range =_tx('2025-01-15').range('2025-01-15'); // Single day\n    expect(range.contains(_tx())).toBe(true);\n    expect(range.days()).toBe(1);\n  });\n});\n```\n\n**Important Notes:**\n- Freezing time is **global** - affects all `_tx()` calls\n- Always call `_tx.unfreeze()` in test teardown (afterEach/afterAll)\n- Freezing affects only `_tx()` without arguments - explicit dates are unaffected\n- Safe to use in parallel test runners (each test should manage its own freeze state)\n\n## Examples\n\n### Factory Function\n\nCreate dates from various inputs:\n\n```javascript\nimport _tx from '24x7';\n\n// Current time\nconst now = _tx();\nconsole.log(now.format('YYYY-MM-DD HH:mm:ss')); // Current date/time\n\n// From ISO string\nconst date1 =_tx('2025-01-15');\nconst date2 =_tx('2025-01-15T14:30:00Z');\nconst date3 =_tx('2025-01-15T14:30:00.000Z');\n\n// From Date object\nconst nativeDate = new Date('2025-01-15');\nconst date4 =_tx(nativeDate);\n\n// From timestamp (milliseconds)\nconst date5 =_tx(1705334400000); // Unix timestamp\n\n// From timestamp (seconds)\nconst date6 =_tx(1705334400 * 1000);\n\n// Undefined uses current time\nconst date7 =_tx(undefined); // Same as _tx()\n```\n\n### Date Manipulation\n\nAdd or subtract time units:\n\n```javascript\nimport _tx from '24x7';\n\nconst date =_tx('2025-01-15T10:30:00');\n\n// Add milliseconds\ndate.add(1000); // Add 1 second\n\n// Add time units\ndate.addYears(1);    // '2026-01-15T10:30:00'\ndate.addMonths(2);   // '2025-03-15T10:30:00'\ndate.addDays(7);     // '2025-01-22T10:30:00'\ndate.addHours(5);    // '2025-01-15T15:30:00'\ndate.addMinutes(30); // '2025-01-15T11:00:00'\ndate.addSeconds(45);  // '2025-01-15T10:30:45'\n\n// Subtract time units\ndate.subtract(1000);      // Subtract 1 second\ndate.addDays(-7);         // Subtract 7 days (same as subtractDays)\ndate.subtract(7 * 24 * 60 * 60 * 1000); // Subtract 7 days in milliseconds\n\n// Chain operations\nconst result =_tx('2025-01-15')\n  .addMonths(1)\n  .addDays(5)\n  .addHours(2)\n  .format('YYYY-MM-DD HH:mm'); // '2025-02-20 02:00'\n```\n\n### Date Comparison\n\nCompare dates in various ways:\n\n```javascript\nimport _tx from '24x7';\n\nconst date1 =_tx('2025-01-15');\nconst date2 =_tx('2025-01-20');\nconst date3 =_tx('2025-01-15');\n\n// Before/After checks\ndate1.isBefore(date2);  // true\ndate1.isAfter(date2);   // false\ndate1.isSame(date3);    // true\n\n// Compare with different input types\ndate1.isBefore('2025-01-20');        // true (string)\ndate1.isBefore(new Date('2025-01-20')); // true (Date object)\ndate1.isBefore(1705334400000);        // true (timestamp)\n\n// Between check (inclusive)\nconst start =_tx('2025-01-10');\nconst end =_tx('2025-01-20');\nconst middle =_tx('2025-01-15');\n\nmiddle.isBetween(start, end);  // true\nstart.isBetween(start, end);   // true (inclusive)\nend.isBetween(start, end);     // true (inclusive)\nx('2025-01-25').isBetween(start, end); // false\n\n// Real-world example: Check if date is in current month\nconst today = _tx();\nconst monthStart = today.startOfMonth();\nconst monthEnd = today.endOfMonth();\nconst isInCurrentMonth = today.isBetween(monthStart, monthEnd); // Always true\n```\n\n### Date Information\n\nExtract date components:\n\n```javascript\nimport _tx from '24x7';\n\nconst date =_tx('2025-01-15T14:30:45.123');\n\n// Get date parts\ndate.year();        // 2025\ndate.month();       // 0 (January, 0-indexed)\ndate.date();        // 15 (day of month, 1-indexed)\ndate.day();         // 3 (Wednesday, 0=Sunday)\ndate.hour();        // 14\ndate.minute();      // 30\ndate.second();      // 45\ndate.millisecond(); // 123\n\n// Use in calculations\nconst isWeekend = date.day() === 0 || date.day() === 6;\nconst isJanuary = date.month() === 0;\nconst isLeapYear = date.year() % 4 === 0 && (date.year() % 100 !== 0 || date.year() % 400 === 0);\n\n// Format with extracted values\nconst customFormat = `${date.year()}-${String(date.month() + 1).padStart(2, '0')}-${String(date.date()).padStart(2, '0')}`;\n```\n\n### Start/End of Periods\n\nGet boundaries of time periods:\n\n```javascript\nimport _tx from '24x7';\n\nconst date =_tx('2025-01-15T14:30:45');\n\n// Day boundaries\ndate.startOfDay();  // '2025-01-15T00:00:00.000'\ndate.endOfDay();    // '2025-01-15T23:59:59.999'\n\n// Month boundaries\ndate.startOfMonth(); // '2025-01-01T00:00:00.000'\ndate.endOfMonth();   // '2025-01-31T23:59:59.999'\n\n// Year boundaries\ndate.startOfYear();  // '2025-01-01T00:00:00.000'\ndate.endOfYear();    // '2025-12-31T23:59:59.999'\n\n// Common use case: Get all dates in current month\nconst monthStart = _tx().startOfMonth();\nconst monthEnd = _tx().endOfMonth();\nconst daysInMonth = monthEnd.date(); // 28-31 depending on month\n\n// Get first Monday of month\nconst firstDay =_tx('2025-01-15').startOfMonth();\nconst firstMonday = firstDay.addDays((8 - firstDay.day()) % 7 || 7);\n```\n\n### Conversion\n\nConvert to different formats:\n\n```javascript\nimport _tx from '24x7';\n\nconst date =_tx('2025-01-15T14:30:45.123');\n\n// To native Date object (cloned for safety)\nconst nativeDate = date.toDate();\nconsole.log(nativeDate instanceof Date); // true\n\n// To timestamp\nconst timestamp = date.valueOf(); // or date.getTime()\nconsole.log(timestamp); // 1705334445123\n\n// To ISO string\nconst isoString = date.toISOString();\nconsole.log(isoString); // '2025-01-15T14:30:45.123Z'\n\n// Implicit conversion (uses valueOf)\nconst num = +date; // Same as date.valueOf()\nconst str = String(date); // Uses toString()\n\n// Use with native Date methods\nconst utcString = date.toDate().toUTCString();\n```\n\n### Timezone\n\nWork with different timezones (default is UTC):\n\n```javascript\nimport _tx from '24x7';\n\n// Default timezone is UTC\nconst date =_tx('2025-01-15T10:00:00Z');\nconsole.log(date.tz()); // 'UTC'\nconsole.log(date.isUTC()); // true\n\n// Convert to local timezone\nconst local = date.toLocal();\nconsole.log(local.tz()); // 'local'\nconsole.log(local.isLocal()); // true\n\n// Convert to specific IANA timezone (chaining works!)\nconst kolkata = date.tz('Asia/Kolkata');\nconsole.log(kolkata.tz()); // 'Asia/Kolkata'\nconsole.log(kolkata.format('YYYY-MM-DD HH:mm:ss')); // Shows time in Kolkata timezone\nconsole.log(kolkata.ianaTimezone()); // 'Asia/Kolkata'\n\n// Convert to another timezone\nconst nyDate = date.toTimezone('America/New_York');\nconsole.log(nyDate.tz()); // 'America/New_York'\n\n// Convert back to UTC\nconst backToUTC = nyDate.toUTC();\nconsole.log(backToUTC.isUTC()); // true\n\n// Get timezone offset\nconsole.log(date.timezoneOffset()); // 0 (minutes)\nconsole.log(date.timezoneOffsetString()); // '+00:00'\nconsole.log(kolkata.timezoneOffsetString()); // '+05:30'\n\n// Set global default timezone\n_tx.config({\n  time: {\n    timezone: 'America/Los_Angeles'\n  }\n});\nconst pacificDate =_tx('2025-01-15T10:00:00Z');\nconsole.log(pacificDate.tz()); // 'America/Los_Angeles'\n```\n\n#### Supported Timezones\n\n- **UTC** - Coordinated Universal Time (default)\n- **local** - System's local timezone\n- **IANA timezones** - Any valid IANA timezone identifier (e.g., `'America/New_York'`, `'Asia/Kolkata'`, `'Europe/London'`)\n\n#### Timezone Methods\n\n```javascript\ndate.tz()                    // Get current timezone\ndate.tz(timezone)            // Set timezone (returns DateTime for chaining)\ndate.toTimezone(timezone)    // Convert to timezone (alternative method)\ndate.toUTC()                 // Convert to UTC\ndate.toLocal()                // Convert to local timezone\ndate.timezoneOffset()         // Get offset in minutes\ndate.timezoneOffsetString()   // Get offset as string (e.g., '+05:30')\ndate.isUTC()                 // Check if UTC\ndate.isLocal()               // Check if local\ndate.ianaTimezone()          // Get IANA timezone name or null\n```\n\n#### Timezone-Aware Date Components\n\nAll date component methods (`year()`, `month()`, `date()`, `hour()`, `minute()`, `second()`, etc.) automatically respect the timezone:\n\n```javascript\nconst utc =_tx('2025-01-15T10:00:00Z');\nconsole.log(utc.hour()); // 10 (UTC)\n\nconst kolkata = utc.tz('Asia/Kolkata');\nconsole.log(kolkata.hour()); // 15 (IST, UTC+5:30)\n\n// Formatting also respects timezone\nconsole.log(utc.format('YYYY-MM-DD HH:mm:ss')); // '2025-01-15 10:00:00'\nconsole.log(kolkata.format('YYYY-MM-DD HH:mm:ss')); // '2025-01-15 15:30:00'\n```\n\n#### Real-World Timezone Examples\n\n```javascript\nimport _tx from '24x7';\n\n// Example 1: Convert meeting time across timezones\nconst meetingUTC =_tx('2025-01-15T14:00:00Z');\nconst meetingNY = meetingUTC.tz('America/New_York');\nconst meetingLA = meetingUTC.tz('America/Los_Angeles');\nconst meetingLondon = meetingUTC.tz('Europe/London');\n\nconsole.log('Meeting times:');\nconsole.log('UTC:', meetingUTC.format('YYYY-MM-DD HH:mm'));\nconsole.log('New York:', meetingNY.format('YYYY-MM-DD HH:mm'));\nconsole.log('Los Angeles:', meetingLA.format('YYYY-MM-DD HH:mm'));\nconsole.log('London:', meetingLondon.format('YYYY-MM-DD HH:mm'));\n\n// Example 2: Calculate time difference between timezones\nconst now = _tx();\nconst nyTime = now.tz('America/New_York');\nconst offset = nyTime.timezoneOffset() - now.timezoneOffset();\nconsole.log(`Time difference: ${offset} minutes`);\n\n// Example 3: Display user's local time\nfunction displayUserTime(userTimezone) {\n  const now = _tx().tz(userTimezone);\n  return now.format('YYYY-MM-DD HH:mm:ss');\n}\n\nconsole.log(displayUserTime('Asia/Kolkata')); // User's local time in Kolkata\nconsole.log(displayUserTime('America/New_York')); // User's local time in NY\n```\n\n### Format Patterns\n\nFormat dates with custom patterns:\n\n```javascript\nimport _tx from '24x7';\n\nconst date =_tx('2025-01-15T14:30:45');\n\n// Common formats\ndate.format('YYYY-MM-DD');           // '2025-01-15'\ndate.format('MM/DD/YYYY');           // '01/15/2025'\ndate.format('DD-MM-YYYY');           // '15-01-2025'\ndate.format('YYYY-MM-DD HH:mm:ss');  // '2025-01-15 14:30:45'\n\n// Human-readable formats\ndate.format('MMMM D, YYYY');         // 'January 15, 2025'\ndate.format('MMM D, YYYY');          // 'Jan 15, 2025'\ndate.format('dddd, MMMM D, YYYY');   // 'Wednesday, January 15, 2025'\ndate.format('ddd, MMM D');          // 'Wed, Jan 15'\n\n// Time formats\ndate.format('HH:mm');                // '14:30'\ndate.format('HH:mm:ss');             // '14:30:45'\ndate.format('hh:mm A');              // '02:30 PM'\ndate.format('hh:mm a');              // '02:30 pm'\n\n// Combined formats\ndate.format('YYYY-MM-DD HH:mm');     // '2025-01-15 14:30'\ndate.format('MMM D, YYYY [at] hh:mm A'); // 'Jan 15, 2025 at 02:30 PM'\n\n// File-safe format\ndate.format('YYYY-MM-DD_HH-mm-ss');  // '2025-01-15_14-30-45'\n```\n\n## API Reference\n\n### Factory Function\n\n```javascript\n_t_tx()                                    // Current time (or frozen time)\n_tx('2025-01-15')                        // Parse string (ISO format)\n_tx('23/01/2025', 'DD/MM/YYYY')          // Parse with format\n_tx('2025-01-15', { immutable: false })  // With config object\n_tx(new Date())                          // From Date object\n_tx(1234567890)                          // From timestamp\n```\n\n### Configuration Methods\n\n```javascript\n_tx.config()              // Get current configuration\n_tx.config(options)       // Set configuration (deep merge)\n_tx.resetConfig()          // Reset to DEFAULT_CONFIG\n```\n\n### Immutability Control\n\n```javascript\ndate.immutable(true)    // Enable immutability (default)\ndate.immutable(false)   // Disable immutability (mutable mode)\ndate.isImmutable()      // Check if instance is immutable\n```\n\n### Date Manipulation\n\n```javascript\ndate.add(ms)           // Add milliseconds (returns new instance if immutable)\ndate.subtract(ms)      // Subtract milliseconds (returns new instance if immutable)\ndate.addYears(n)       // Add years\ndate.addMonths(n)      // Add months\ndate.addDays(n)        // Add days\ndate.addHours(n)       // Add hours\ndate.addMinutes(n)     // Add minutes\ndate.addSeconds(n)     // Add seconds\n```\n\n### Interval Methods\n\n```javascript\ndate.interval(end)     // Create interval from date to end\n_tx.interval(start, end)  // Static method to create interval\n\ninterval.contains(date | interval)  // Check if contains date or interval\ninterval.overlaps(other, options)   // Check if overlaps with another interval\ninterval.intersect(other)           // Get intersection interval or null\ninterval.clamp(other)               // Clamp interval to fit within this\ninterval.splitBy(unit | duration)   // Split into array of intervals\ninterval.iterate(unit)              // Iterator over interval\ninterval.duration(unit?)            // Get duration in specified unit\n_tx.merge(intervals[])                // Merge multiple intervals\n```\n\n### Date Comparison\n\n```javascript\ndate.isBefore(other)   // Check if before\ndate.isAfter(other)    // Check if after\ndate.isSame(other)     // Check if equal\ndate.isBetween(start, end) // Check if between\n```\n\n### Date Information\n\n```javascript\ndate.year()            // Get year\ndate.month()           // Get month (0-11)\ndate.date()            // Get day of month (1-31)\ndate.day()             // Get day of week (0-6)\ndate.hour()            // Get hour (0-23)\ndate.minute()          // Get minute (0-59)\ndate.second()          // Get second (0-59)\ndate.millisecond()     // Get millisecond (0-999)\n```\n\n### Start/End of Periods\n\n```javascript\ndate.startOfDay()      // Start of day (00:00:00.000)\ndate.endOfDay()        // End of day (23:59:59.999)\ndate.startOfMonth()    // Start of month\ndate.endOfMonth()      // End of month\ndate.startOfYear()     // Start of year\ndate.endOfYear()       // End of year\n```\n\n### Conversion\n\n```javascript\ndate.toDate()          // Get native Date object\ndate.valueOf()         // Get timestamp\ndate.getTime()         // Get timestamp\ndate.toISOString()     // Get ISO string\ndate.format(pattern)   // Format with pattern (requires format plugin)\n\n// Timezone methods\ndate.tz()              // Get current timezone (or set with date.tz('Asia/Kolkata'))\ndate.tz(timezone)      // Set timezone and return DateTime (for chaining)\ndate.timezone()        // Alias for tz() (backward compatibility)\ndate.toTimezone(tz)    // Convert to timezone\ndate.toUTC()           // Convert to UTC\ndate.toLocal()         // Convert to local\ndate.timezoneOffset()  // Get offset in minutes\ndate.timezoneOffsetString() // Get offset as string (e.g., '+05:30')\ndate.isUTC()           // Check if UTC\ndate.isLocal()         // Check if local\ndate.ianaTimezone()    // Get IANA timezone name or null\n```\n\n### Format Patterns\n\n```javascript\ndate.format('YYYY-MM-DD')        // '2025-01-15'\ndate.format('MMM D, YYYY')       // 'Jan 15, 2025'\ndate.format('YYYY-MM-DD HH:mm')  // '2025-01-15 14:30'\ndate.format('dddd, MMMM D, YYYY') // 'Wednesday, January 15, 2025'\n```\n\n**Pattern tokens:**\n- `YYYY` - 4-digit year\n- `YY` - 2-digit year\n- `MMMM` - Full month name\n- `MMM` - Short month name\n- `MM` - 2-digit month\n- `M` - Month number\n- `DD` - 2-digit day\n- `D` - Day number\n- `dddd` - Full day name\n- `ddd` - Short day name\n- `HH` - 24-hour format (2-digit)\n- `hh` - 12-hour format (2-digit)\n- `mm` - Minutes (2-digit)\n- `ss` - Seconds (2-digit)\n- `A` - AM/PM\n- `a` - am/pm\n\n## Plugin System\n\nPlugins extend the DateTime prototype. All plugins are included by default, but you can create custom plugins:\n\n#### Basic Plugin Example\n\n```javascript\nimport _tx, { DateTime } from '24x7';\n\n// Simplest form: Named function becomes the method\nfunction myMethod() {\n  // Your custom method\n  return this;\n}\n\n_tx.extend(myMethod);\n\n// Now you can use it\n_tx().myMethod();\n\n// Alternative 1: Explicit method name\n_tx.extend('myMethod2', function() {\n  return this;\n});\n\n// Alternative 2: Install function (for multiple methods)\n_tx.extend((DateTime) => {\n  DateTime.prototype.method1 = function() { return this; };\n  DateTime.prototype.method2 = function() { return this; };\n});\n\n// Alternative 3: Object with install method (also supported)\nconst myPlugin = {\n  install(DateTime) {\n    DateTime.prototype.myMethod3 = function() {\n      return this;\n    };\n  }\n};\n\n_tx.extend(myPlugin);\n```\n\n#### Advanced Plugin Examples\n\n```javascript\nimport _tx, { DateTime } from '24x7';\n\n// Example 1: Add timezone offset methods (install function for multiple methods)\n_tx.extend((DateTime) => {\n  DateTime.prototype.getTimezoneOffset = function() {\n    return this.toDate().getTimezoneOffset();\n  };\n\n  DateTime.prototype.toUTC = function() {\n    const date = this.toDate();\n    const utcDate = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));\n    return new DateTime(utcDate);\n  };\n});\n\n_tx.extend(timezonePlugin);\n\n// Usage\nconst date =_tx('2025-01-15T14:30:00');\nconsole.log(date.getTimezoneOffset()); // -480 (PST)\nconst utc = date.toUTC();\n\n// Example 2: Add age calculation (direct method)\nfunction age(referenceDate = _tx()) {\n  const ref = referenceDate instanceof DateTime \n    ? referenceDate \n    : new DateTime(new Date(referenceDate));\n  \n  let years = ref.year() - this.year();\n  const monthDiff = ref.month() - this.month();\n  const dayDiff = ref.date() - this.date();\n\n  if (monthDiff < 0 || (monthDiff === 0 && dayDiff < 0)) {\n    years--;\n  }\n\n  return years;\n}\n\n_tx.extend(age);\n\n// Usage\nconst birthDate =_tx('1990-05-15');\nconst age = birthDate.age(); // Age as of today\nconst ageOnDate = birthDate.age(_tx('2025-05-15')); // Age on specific date\n\n// Example 3: Add quarter methods (install function for multiple methods)\n_tx.extend((DateTime) => {\n  DateTime.prototype.quarter = function() {\n    return Math.floor(this.month() / 3) + 1;\n  };\n\n  DateTime.prototype.startOfQuarter = function() {\n    const quarter = this.quarter();\n    const month = (quarter - 1) * 3;\n    const newDate = new Date(this._date);\n    newDate.setMonth(month, 1);\n    newDate.setHours(0, 0, 0, 0);\n    return new DateTime(newDate);\n  };\n\n  DateTime.prototype.endOfQuarter = function() {\n    const quarter = this.quarter();\n    const month = quarter * 3 - 1;\n    const newDate = new Date(this._date);\n    newDate.setMonth(month + 1, 0);\n    newDate.setHours(23, 59, 59, 999);\n    return new DateTime(newDate);\n  };\n});\n\n// Usage\nconst date =_tx('2025-02-15');\nconsole.log(date.quarter()); // 1 (Q1)\nconst quarterStart = date.startOfQuarter(); // 2025-01-01\nconst quarterEnd = date.endOfQuarter(); // 2025-03-31\n\n// Example 4: Add relative time formatting (direct method)\nfunction fromNow() {\n  const now = _tx();\n  const diffMs = now.getTime() - this.getTime();\n  const diffSeconds = Math.floor(diffMs / 1000);\n  const diffMinutes = Math.floor(diffSeconds / 60);\n  const diffHours = Math.floor(diffMinutes / 60);\n  const diffDays = Math.floor(diffHours / 24);\n\n  if (Math.abs(diffSeconds) < 60) {\n    return diffSeconds >= 0 ? 'just now' : 'in a few seconds';\n  } else if (Math.abs(diffMinutes) < 60) {\n    const mins = Math.abs(diffMinutes);\n    return diffMinutes >= 0 ? `${mins} minute${mins > 1 ? 's' : ''} ago` : `in ${mins} minute${mins > 1 ? 's' : ''}`;\n  } else if (Math.abs(diffHours) < 24) {\n    const hrs = Math.abs(diffHours);\n    return diffHours >= 0 ? `${hrs} hour${hrs > 1 ? 's' : ''} ago` : `in ${hrs} hour${hrs > 1 ? 's' : ''}`;\n  } else if (Math.abs(diffDays) < 7) {\n    const days = Math.abs(diffDays);\n    return diffDays >= 0 ? `${days} day${days > 1 ? 's' : ''} ago` : `in ${days} day${days > 1 ? 's' : ''}`;\n  } else {\n    return this.format('MMM D, YYYY');\n  }\n}\n\n_tx.extend(fromNow);\n\n// Usage\nconst past = _tx().subtractHours(2);\nconsole.log(past.fromNow()); // \"2 hours ago\"\n\nconst future = _tx().addDays(3);\nconsole.log(future.fromNow()); // \"in 3 days\"\n```\n\n#### Creating Reusable Plugins\n\n```javascript\n// plugins/custom.js - Single method\nexport default function myMethod() {\n  return this;\n}\n\n// plugins/custom.js - Multiple methods (install function)\nexport default (DateTime) => {\n  DateTime.prototype.method1 = function() { return this; };\n  DateTime.prototype.method2 = function() { return this; };\n};\n\n// In your application\nimport _tx from '24x7';\nimport customPlugin from './plugins/custom.js';\n\n_tx.extend(customPlugin);\n```\n\n#### Plugin Best Practices\n\n```javascript\nimport _tx, { DateTime } from '24x7';\n\n// Single method - use named function\nfunction chainableMethod() {\n  // Do something\n  return this;\n}\n_tx.extend(chainableMethod);\n\n// Multiple methods - use install function\n_tx.extend((DateTime) => {\n  // 1. Always return this for chainability (when appropriate)\n  DateTime.prototype.chainableMethod2 = function() {\n    return this;\n  };\n\n  // 2. Create new DateTime instances for immutable operations\n  DateTime.prototype.immutableOperation = function() {\n    const newDate = new Date(this._date);\n    // Modify newDate\n    return new DateTime(newDate);\n  };\n\n  // 3. Validate inputs\n  DateTime.prototype.safeMethod = function(input) {\n    if (typeof input !== 'number') {\n      throw new TypeError('Expected a number');\n    }\n    // Your logic\n    return this;\n  };\n\n  // 4. Use descriptive method names\n  DateTime.prototype.calculateBusinessHours = function() {\n    // Better than calculateBH()\n    return this;\n  };\n});\n```\n\n## Error Handling\n\n24x7 throws explicit errors for invalid operations:\n\n#### Parsing Errors\n\n```javascript\nimport _tx from '24x7';\n\n// Invalid date string\ntry {\n_tx('invalid-date');\n} catch (error) {\n  console.error(error); // TypeError: Cannot parse date from: invalid-date\n  console.error(error.message); // \"Cannot parse date from: invalid-date\"\n}\n\n// Invalid date object\ntry {\n_tx(new Date('invalid'));\n} catch (error) {\n  console.error(error); // TypeError: Invalid Date object provided\n}\n\n// Invalid input type\ntry {\n_tx({ not: 'a date' });\n} catch (error) {\n  console.error(error); // TypeError: Cannot parse date from type: object\n}\n```\n\n#### Range Errors\n\n```javascript\nimport _tx from '24x7';\n\n// Start date after end date\ntry {\n_tx('2025-01-10').range('2025-01-05'); // start > end\n} catch (error) {\n  console.error(error); // RangeError: Start date must be before or equal to end date\n}\n\n// Valid range (no error)\nconst validRange =_tx('2025-01-05').range('2025-01-10'); // OK\nconst singleDayRange =_tx('2025-01-05').range('2025-01-05'); // OK (same day)\n```\n\n#### Business Day Errors\n\n```javascript\nimport _tx from '24x7';\n\n// Invalid weekends array\ntry {\n_tx('2025-01-10').addBusinessDays(5, {\n    weekends: 'not an array' // Should be array\n  });\n} catch (error) {\n  console.error(error); // TypeError: weekends must be an array\n}\n\n// Invalid weekend values\ntry {\n_tx('2025-01-10').addBusinessDays(5, {\n    weekends: [0, 7] // 7 is invalid (0-6 only)\n  });\n} catch (error) {\n  console.error(error); // TypeError: weekends must be an array of numbers 0-6\n}\n\n// Invalid days parameter\ntry {\n_tx('2025-01-10').addBusinessDays('five'); // Should be number\n} catch (error) {\n  console.error(error); // TypeError: addBusinessDays() expects a number\n}\n```\n\n#### Comparison Errors\n\n```javascript\nimport _tx from '24x7';\n\n// Invalid comparison value\ntry {\n_tx('2025-01-10').isBefore('not-a-date');\n} catch (error) {\n  console.error(error); // TypeError: Cannot compare with invalid date: not-a-date\n}\n\n// Valid comparisons\nx('2025-01-10').isBefore('2025-01-15'); // true (no error)\nx('2025-01-10').isBefore(new Date('2025-01-15')); // true (no error)\n```\n\n#### Format Errors\n\n```javascript\nimport _tx from '24x7';\n\n// Invalid pattern type\ntry {\n_tx('2025-01-15').format(123); // Should be string\n} catch (error) {\n  console.error(error); // TypeError: format() expects a string pattern\n}\n\n// Valid format\nx('2025-01-15').format('YYYY-MM-DD'); // '2025-01-15' (no error)\n```\n\n#### Manipulation Errors\n\n```javascript\nimport _tx from '24x7';\n\n// Invalid add/subtract values\ntry {\n_tx('2025-01-15').add('not a number');\n} catch (error) {\n  console.error(error); // TypeError: add() expects a number (milliseconds)\n}\n\ntry {\n_tx('2025-01-15').addDays('five');\n} catch (error) {\n  console.error(error); // TypeError: addDays() expects a number\n}\n\n// Valid operations\nx('2025-01-15').add(1000); // OK\nx('2025-01-15').addDays(5); // OK\n```\n\n#### Error Handling Best Practices\n\n```javascript\nimport _tx from '24x7';\n\n// Pattern 1: Try-catch for user input\nfunction parseUserDate(input) {\n  try {\n    return _tx(input);\n  } catch (error) {\n    console.error('Invalid date input:', input);\n    return null; // or return a default date\n  }\n}\n\n// Pattern 2: Validate before operations\nfunction safeAddBusinessDays(date, days, options) {\n  if (typeof days !== 'number') {\n    throw new TypeError('Days must be a number');\n  }\n  \n  try {\n    return _tx(date).addBusinessDays(days, options);\n  } catch (error) {\n    console.error('Error adding business days:', error);\n    throw error; // Re-throw or handle as needed\n  }\n}\n\n// Pattern 3: Graceful degradation\nfunction getDateOrNow(input) {\n  try {\n    return _tx(input);\n  } catch {\n    return _tx(); // Fallback to current time\n  }\n}\n\n// Pattern 4: Type checking\nfunction isValidDateInput(input) {\n  try {\n  _tx(input);\n    return true;\n  } catch {\n    return false;\n  }\n}\n\n// Usage\nif (isValidDateInput(userInput)) {\n  const date =_tx(userInput);\n  // Process date\n} else {\n  // Show error to user\n  console.error('Please enter a valid date');\n}\n```\n\n## Browser and Node.js Support\n\n- **ES2020+** required\n- **Node.js**: 14+ (or any environment with ES modules)\n- **Browsers**: Modern browsers with ES module support\n\n## Design Principles\n\n1. **Immutability**: All operations return new instances\n2. **Explicit APIs**: No magic, no surprises\n3. **Predictable behavior**: DST changes don't silently corrupt data\n4. **Small core**: Extensible via plugins\n5. **No dependencies**: Self-contained\n6. **Tree-shakable**: Import only what you need\n\n## License\n\nSee [LICENSE](LICENSE) file for details.\n\n## Contributing\n\nThis is a production-ready library. Contributions should maintain:\n- Immutability guarantees\n- Explicit error handling\n- Comprehensive documentation\n- Test coverage\n\n## Non-Goals\n\n24x7 explicitly does **not** provide:\n- Moment.js compatibility layer\n- Large locale databases\n- Full timezone engine\n- Implicit magic behavior\n\nThese are intentional design decisions to keep the library focused and maintainable.\n","readmeFilename":"README.md","_rev":"1-ceb75aea3e53bfc72d115a833df759fc"}