A tiny and dependency-free datetime library with a chainable and immutable API.
- 🔄 Immutable operations - All operations return new instances, preventing accidental state mutations
- 🔗 Chainable API - Fluent interface for composing multiple operations
- 📅 UTC-based - Works with UTC milliseconds internally, avoiding timezone complexities
- ⚡ Zero dependencies - Tiny footprint, built without any external dependencies
- 🎯 Type-safe - Written in TypeScript with full type definitions
npm install millis-js
This library provides three classes: DateTime
, Duration
, and Interval
.
The DateTime
class represents a millisecond timestamp.
Factory methods return a new DateTime
instance.
-
DateTime.now(): DateTime
: Returns a new DateTime representing the current UTC timeDateTime.now();
-
DateTime.from(dateTime: DateTimeLike): DateTime
: Returns a new DateTime from a date time like object// From milliseconds timestamp DateTime.from(1_704_067_200_000); // From strings DateTime.from('2024-01-01T00:00:00.000Z'); // ISO DateTime.from('2024-01-01'); // YYYY-MM-DD DateTime.from('2024-001'); // YYYY-DDD // From Date object DateTime.from(new Date()); // From DateTime object DateTime.from(DateTime.now()); // From calendar date components DateTime.from({ year: 2024, month: 1, dayOfMonth: 1, hour: 12, // optional minute: 30, // optional second: 15, // optional millisecond: 0 // optional }); // From ordinal date components DateTime.from({ year: 2024, dayOfYear: 1, hour: 12 // optional, etc. });
-
DateTime.until(dateTime: DateTimeLike): Interval
: Returns an Interval from the current time to a given date time// Creates interval spanning one day DateTime.now().until(DateTime.now().plus({ days: 1 })) // Interval object
DateTime accepts both absolute (days, hours, minutes, seconds, milliseconds) and relative (months, years) durations.
-
plus(duration: DurationLike): DateTime
: Returns a DateTime with the duration added// Add absolute durations (days and smaller units) DateTime.from('2024-01-01T00:00:00.000Z').plus({ days: 1, hours: 2, minutes: 30 }) // 2024-01-02T02:30:00.000Z // Add relative durations (months/years) DateTime.from('2024-01-31T00:00:00.000Z').plus({ months: 1 }) // 2024-02-29T00:00:00.000Z (handles leap years) // Add Duration object DateTime.from('2024-01-31T00:00:00.000Z').plus(Duration.hours(2)) // 2024-01-31T02:00:00.000Z // Add milliseconds DateTime.from('2024-01-31T00:00:00.000Z').plus(86_400_000) // 2024-02-01T00:00:00.000Z
-
minus(duration: DurationLike): DateTime
: Returns a DateTime with the duration subtracted// Subtract absolute durations DateTime.from('2024-01-01T00:00:00.000Z').minus({ days: 1, hours: 2 }) // 2023-12-30T22:00:00.000Z // Subtract relative durations DateTime.from('2024-03-31T00:00:00.000Z').minus({ months: 1 }) // 2024-02-29T00:00:00.000Z (handles leap years) // Subtract Duration object DateTime.from('2024-01-31T00:00:00.000Z').minus(Duration.hours(2)) // 2024-01-30T22:00:00.000Z // Subtract milliseconds DateTime.from('2024-01-31T00:00:00.000Z').minus(86_400_000) // 2023-12-31T00:00:00.000Z
-
millis(): number
: Returns the milliseconds since Unix EpochDateTime.from('2024-01-01T00:00:00.000Z').millis() // 1_704_067_200_000
-
timestamp(): number
: Returns the seconds since Unix Epoch (floored)DateTime.from('2024-01-01T00:00:00.500Z').timestamp() // 1_704_067_200
-
date(): Date
: Returns a JavaScript Date objectDateTime.from('2024-01-01T00:00:00.000Z').date() // new Date("2024-01-01T00:00:00.000Z")
-
year(): number
: Returns the calendar yearDateTime.from('2024-01-01T00:00:00.000Z').year() // 2024
-
month(): number
: Returns the calendar month (1-12)DateTime.from('2024-01-01T00:00:00.000Z').month() // 1
-
dayOfMonth(): number
: Returns the day of month (1-31)DateTime.from('2024-01-01T00:00:00.000Z').dayOfMonth() // 1
-
dayOfYear(): number
: Returns the day of year (1-365/366)DateTime.from('2024-01-01T00:00:00.000Z').dayOfYear() // 1 DateTime.from('2024-12-31T00:00:00.000Z').dayOfYear() // 366 (leap year)
-
hour(): number
: Returns the hour of day (0-23)DateTime.from('2024-01-01T12:00:00.000Z').hour() // 12
-
minute(): number
: Returns the minute of hour (0-59)DateTime.from('2024-01-01T12:30:00.000Z').minute() // 30
-
second(): number
: Returns the second of minute (0-59)DateTime.from('2024-01-01T12:30:15.000Z').second() // 15
-
equals(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is equal to the given date timeDateTime.from('2024-01-01T12:30:15.000Z').equals(DateTime.from('2024-01-01T12:30:15.000Z')) // true
-
compare(dateTime: DateTimeLike): number
: Returns a comparison value of two DateTime objects to be used in sorting[ DateTime.from('2024-01-31T00:00:00.000Z'), DateTime.from('2024-01-02T00:00:00.000Z'), DateTime.from('2024-01-31T00:00:00.000Z'), ].sort((a, b) => a.compare(b)) // [2024-01-01T00:00:00.000Z, 2024-01-02T00:00:00.000Z, 2024-01-31T00:00:00.000Z]
-
isBefore(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is before the given date timeDateTime.from('2024-01-01T12:30:15.000Z').isBefore('2024-01-01T12:30:16.000Z') // true
-
isAfter(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is after the given date timeDateTime.from('2024-01-01T12:30:15.000Z').isAfter('2024-01-01T12:30:14.000Z') // true
-
isBetween(start: DateTimeLike, end: DateTimeLike): boolean
: Returns true if the current DateTime is between the given start and end date timesDateTime.from('2024-01-01T12:30:15.000Z').isBetween('2024-01-01T12:30:14.000Z', '2024-01-01T12:30:16.000Z') // true
-
isSameSecond(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is in the same second as the given DateTimeDateTime.from('2024-01-01T12:30:15.123Z').isSameSecond('2024-01-01T12:30:15.456Z') // true
-
isSameMinute(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is in the same minute as the given DateTimeDateTime.from('2024-01-01T12:30:15.000Z').isSameMinute('2024-01-01T12:30:45.000Z') // true
-
isSameHour(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is in the same hour as the given DateTimeDateTime.from('2024-01-01T12:30:00.000Z').isSameHour('2024-01-01T12:45:00.000Z') // true
-
isSameDay(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is in the same day as the given DateTimeDateTime.from('2024-01-01T12:00:00.000Z').isSameDay('2024-01-01T23:59:59.999Z') // true
-
isSameMonth(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is in the same month as the given DateTimeDateTime.from('2024-01-01T00:00:00.000Z').isSameMonth('2024-01-31T23:59:59.999Z') // true
-
isSameYear(dateTime: DateTimeLike): boolean
: Returns true if the current DateTime is in the same year as the given DateTimeDateTime.from('2024-01-01T00:00:00.000Z').isSameYear('2024-12-31T23:59:59.999Z') // true
-
isStartOfYear(): boolean
: Returns true if the current DateTime is at the start of the yearDateTime.from('2024-01-01T00:00:00.000Z').isStartOfYear() // true
-
isStartOfMonth(): boolean
: Returns true if the current DateTime is at the start of the monthDateTime.from('2024-01-01T00:00:00.000Z').isStartOfMonth() // true
-
isStartOfDay(): boolean
: Returns true if the current DateTime is at the start of the dayDateTime.from('2024-03-15T00:00:00.000Z').isStartOfDay() // true
-
isStartOfHour(): boolean
: Returns true if the current DateTime is at the start of the hourDateTime.from('2024-03-15T12:00:00.000Z').isStartOfHour() // true
-
isStartOfMinute(): boolean
: Returns true if the current DateTime is at the start of the minuteDateTime.from('2024-03-15T12:30:00.000Z').isStartOfMinute() // true
-
isStartOfSecond(): boolean
: Returns true if the current DateTime is at the start of the secondDateTime.from('2024-03-15T12:30:15.000Z').isStartOfSecond() // true
-
isEndOfYear(): boolean
: Returns true if the current DateTime is at the end of the yearDateTime.from('2024-12-31T23:59:59.999Z').isEndOfYear() // true
-
isEndOfMonth(): boolean
: Returns true if the current DateTime is at the end of the monthDateTime.from('2024-03-31T23:59:59.999Z').isEndOfMonth() // true
-
isEndOfDay(): boolean
: Returns true if the current DateTime is at the end of the dayDateTime.from('2024-03-15T23:59:59.999Z').isEndOfDay() // true
-
isEndOfHour(): boolean
: Returns true if the current DateTime is at the end of the hourDateTime.from('2024-03-15T12:59:59.999Z').isEndOfHour() // true
-
isEndOfMinute(): boolean
: Returns true if the current DateTime is at the end of the minuteDateTime.from('2024-03-15T12:34:59.999Z').isEndOfMinute() // true
-
isEndOfSecond(): boolean
: Returns true if the current DateTime is at the end of the secondDateTime.from('2024-03-15T12:34:56.999Z').isEndOfSecond() // true
-
iso(): string
: Returns the ISO string representationDateTime.now().iso() // "2024-01-01T00:00:00.000Z"
-
format(format: DateTimeFormat | Intl.DateTimeFormat): string
: Format the date time using a format string// Built-in formats dateTime.format('YYYY'); // "2024" dateTime.format('YYYY-DDD'); // "2024-001" dateTime.format('YYYY-MM-DD'); // "2024-01-01" dateTime.format('HH:mm:ss'); // "12:30:45" // Using Intl.DateTimeFormat dateTime.format(new Intl.DateTimeFormat('en-US')) // "1/1/2024, 12:30:45 AM"
-
startOfYear(): DateTime
: Returns a new DateTime set to the start of the yearDateTime.from('2024-03-15T12:34:56.789Z').startOfYear() // 2024-01-01T00:00:00.000Z
-
startOfMonth(): DateTime
: Returns a new DateTime set to the start of the monthDateTime.from('2024-03-15T12:34:56.789Z').startOfMonth() // 2024-03-01T00:00:00.000Z
-
startOfDay(): DateTime
: Returns a new DateTime set to the start of the dayDateTime.from('2024-03-15T12:34:56.789Z').startOfDay() // 2024-03-15T00:00:00.000Z
-
startOfHour(): DateTime
: Returns a new DateTime set to the start of the hourDateTime.from('2024-03-15T12:34:56.789Z').startOfHour() // 2024-03-15T12:00:00.000Z
-
startOfMinute(): DateTime
: Returns a new DateTime set to the start of the minuteDateTime.from('2024-03-15T12:34:56.789Z').startOfMinute() // 2024-03-15T12:34:00.000Z
-
startOfSecond(): DateTime
: Returns a new DateTime set to the start of the secondDateTime.from('2024-03-15T12:34:56.789Z').startOfSecond() // 2024-03-15T12:34:56.000Z
-
endOfYear(): DateTime
: Returns a new DateTime set to the end of the yearDateTime.from('2024-03-15T12:34:56.789Z').endOfYear() // 2024-12-31T23:59:59.999Z
-
endOfMonth(): DateTime
: Returns a new DateTime set to the end of the monthDateTime.from('2024-03-15T12:34:56.789Z').endOfMonth() // 2024-03-31T23:59:59.999Z
-
endOfDay(): DateTime
: Returns a new DateTime set to the end of the dayDateTime.from('2024-03-15T12:34:56.789Z').endOfDay() // 2024-03-15T23:59:59.999Z
-
endOfHour(): DateTime
: Returns a new DateTime set to the end of the hourDateTime.from('2024-03-15T12:34:56.789Z').endOfHour() // 2024-03-15T12:59:59.999Z
-
endOfMinute(): DateTime
: Returns a new DateTime set to the end of the minuteDateTime.from('2024-03-15T12:34:56.789Z').endOfMinute() // 2024-03-15T12:34:59.999Z
-
endOfSecond(): DateTime
: Returns a new DateTime set to the end of the secondDateTime.from('2024-03-15T12:34:56.789Z').endOfSecond() // 2024-03-15T12:34:56.999Z
The Duration
class represents a length of time in milliseconds.
Factory methods return a new Duration
instance.
-
Duration.from(duration: DurationLike): Duration
: Returns a Duration from a duration like object// From components Duration.from({ days: 1, hours: 2, minutes: 30 }) // P1DT2H30M // From milliseconds Duration.from(93_600_000) // P1DT2H
-
Duration.between(start: DateTimeLike, end: DateTimeLike): Duration
: Returns a Duration from a start and end date time// From ISO strings Duration.between('2024-01-01T00:00:00.000Z', '2024-01-02T00:00:00.000Z') // From DateTime objects Duration.between(DateTime.now(), DateTime.now().plus({ days: 1 })) // From milliseconds Duration.between(1704067200000, 1704067200000 + 24 * 60 * 60 * 1000) // From Date objects Duration.between(new Date(), new Date().setDate(new Date().getDate() + 1)) // From datetime components Duration.between({ year: 2024, month: 1, dayOfMonth: 1 }, { year: 2025, month: 1, dayOfMonth: 1 }) // From formatted strings Duration.between({ 'YYYY': '2024' }, { 'YYYY': '2025' })
Duration accepts only absolute durations (days, hours, minutes, seconds, milliseconds).
-
plus(duration: AbsoluteDuration): Duration
: Returns a Duration by adding a durationDuration.hours(2).plus({ minutes: 30 }) // 2.5 hours
-
minus(duration: AbsoluteDuration): Duration
: Returns a Duration by subtracting a durationDuration.hours(5).minus({ hours: 2, minutes: 30 }) // 2.5 hours
-
abs(): Duration
: Returns a Duration with the absolute value of the current durationDuration.hours(-2).abs() // 2 hours
-
days(): number
: Returns the duration in days// Precise value Duration.hours(25).days() // 1.0416666666666667 // Rounded value Duration.hours(25).days({ round: true }) // 1
-
hours(): number
: Returns the duration in hoursDuration.minutes(150).hours() // 2.5 Duration.minutes(150).hours({ round: true }) // 3
-
minutes(): number
: Returns the duration in minutesDuration.seconds(150).minutes() // 2.5 Duration.seconds(150).minutes({ round: true }) // 3
-
seconds(): number
: Returns the duration in secondsDuration.millis(2500).seconds() // 2.5 Duration.millis(2500).seconds({ round: true }) // 3
-
millis(): number
: Returns the duration in millisecondsDuration.seconds(1.5).millis() // 1500
-
iso(): string
: Returns the ISO duration stringDuration.from({ days: 1, hours: 2, minutes: 30 }).iso() // "P1DT2H30M"
The Interval
class represents a time span between two DateTime
instances.
Factory methods return a new Interval
instance.
-
Interval.between(start: DateTimeLike, end: DateTimeLike): Interval
: Returns an Interval between two date timesInterval.between('2024-01-01T00:00:00.000Z','2024-01-02T00:00:00.000Z') // 2024-01-01T00:00:00.000Z/2024-01-02T00:00:00.000Z
-
Interval.days(days: number): Interval
: Returns an Interval spanning the specified number of days from now// Creates interval from now to 7 days in future Interval.days(7) // 2024-01-01T00:00:00.000Z/2024-01-08T00:00:00.000Z // Creates interval from now to 7 days in past Interval.days(-7) // 2024-01-01T00:00:00.000Z/2023-12-25T00:00:00.000Z
-
duration(): Duration
: Returns a Duration representing the length of the intervalInterval.between('2024-01-01T00:00:00.000Z', '2024-01-02T23:59:59.999Z').duration() // 2 days
-
starts(): DateTime
: Returns a DateTime representing the start of the intervalInterval.between('2024-01-01T00:00:00.000Z', '2024-01-02T23:59:59.999Z').starts() // 2024-01-01T00:00:00.000Z
-
ends(): DateTime
: Returns a DateTime representing the end of the intervalInterval.between('2024-01-01T00:00:00.000Z', '2024-01-02T23:59:59.999Z').ends() // 2024-01-02T23:59:59.999Z
-
days(): Array<DateTime>
: Returns an array of DateTimes for each day in the intervalInterval.between('2024-01-01T00:00:00.000Z', '2024-01-02T23:59:59.999Z').days() // [2024-01-01T00:00:00.000Z, 2024-01-02T23:59:59.999Z]
-
years(): Array<DateTime>
: Returns an array of DateTimes for each year in the intervalInterval.between('2024-01-01T00:00:00.000Z', '2025-01-01T23:59:59.999Z').years() // [2024-01-01T00:00:00.000Z, 2025-01-01T23:59:59.999Z]
-
contains(dateTime: DateTimeLike): boolean
: Returns true if the interval contains the given date timeInterval.between('2024-01-01T00:00:00.000Z', '2024-01-02T00:00:00.000Z').contains('2024-01-01T12:00:00.000Z') // true
-
iso(): string
: Returns the ISO interval string representationInterval.between('2024-01-01T00:00:00.000Z', '2024-01-02T00:00:00.000Z').iso() // "2024-01-01T00:00:00.000Z/2024-01-02T00:00:00.000Z"
MIT