Utility methods for working with dates and date ranges
- Valiate
- date.isValid(date) - whether the date provided is an invalid date
- Parse
- date.parse(String) - parse a date and throw an exception if it is not a valid date
- Timezones
- date.toLocalISO - prints in 8601 format with timezone offset based on a tz entry - like america/chicago
- date.localISOFormatter - prints in 8601 format - slightly improved performance for large scale use
- date.getTimezoneOffset(String) - gets the number of milliseconds offset for a given timezone
- date.correctForTimezone(Date, String) - meant to correct a date already off from UTC to the correct time
- date.epochShift(Date, String) - offsets a date from UTC to a given time amount
- knowing some methods might behave incorrectly
- Add
- date.add(Date, {days, hours, minutes, seconds) - shift a date by a given amount
- date.endOfDay(Date) - finds the end of day UTC for a given date
- date.startOfDay(Date) - finds the end of day UTC for a given date
- Overwrite
- date.overwrite(targetDate, newValue) - overwrite the value inside a Date
- date.clone(targetDate) - clone the value of a Date, so it is not modified
- Print
- date.durationLong(epoch) - displays duration in legible form:
D days, H hours, M minutes, S.MMM seconds
- date.durationISO(epoch) - displays duration in condensed forme:
- date.durationLong(epoch) - displays duration in legible form:
- Generate Date Sequence
- date.arrange(startDate, count, incOptions) - create a sequence of dates by continually adding to them
- date.generateDateSequence(startDate, endDate, incOptions) - create a sequence of dates by continually adding between dates
- DateRange.fromList() - pass a sequence of dates to create a list of DateRanges
See other libraries for more complete functionality:
- Luxon - successor to Moment.js
- date-fns-tz extension for date-fns
also watch the TC39 Temporal Proposal
- also found under caniuse: https://caniuse.com/temporal
List of timezone supported is based on the version of javascript used.
Please see:
Classes
Members
(static) TIME
Collection of time durations in milliseconds
Methods
(static) add(dateValue, options) → {Date}
Adds an amount to a date: days, hours, minutes, seconds
d = new Date('2024-12-26 6:00:00');
d30 = utils.date.add(d, { minutes: 30 }); // Date('2024-12-26 6:00:00')
Parameters:
Name | Type | Description | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
dateValue |
Date | date to add to |
|||||||||||||||||||||||||||||||||||
options |
Object | options of what to add Properties
|
Returns:
- Date with the interval added in
- Type
- Date
(static) arrange(startDate, count, options) → {Array.<Date>}
- See:
-
- utils.date.add
- date.generateDateSequence - finish at an endingDate instead of # of iterations
- DateRange.fromList - to create Date Ranges from these dates.
Creates an array of dates, starting with the startDate, and adding in the options count number of times.
const startDate = new Date('2025-02-02');
utils.date.arrange(startDate, 6, { days: 1 });
// ['2025-02-02 00:00:00')
// ['2025-02-03 00:00:00')
// ['2025-02-04 00:00:00')
// ['2025-02-05 00:00:00')
// ['2025-02-06 00:00:00')
// ['2025-02-07 00:00:00')
// ['2025-02-08 00:00:00')
// ['2025-02-09 00:00:00')
// ]
Parameters:
Name | Type | Description | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
startDate |
Date | startingDate to compare to |
|||||||||||||||||||||||||||||||||||
count |
Number | Number of times to add the options |
|||||||||||||||||||||||||||||||||||
options |
Object | options similar to DateUtils.add Properties
|
Returns:
- collection of dates (count long)
- Type
- Array.<Date>
(static) clone(targetDate) → {Date}
Clones a date.
(Doesn't seem needed currently)
(NOTE: the timezone information is lost)
Parameters:
Name | Type | Description |
---|---|---|
targetDate |
Date | the date to be cloned |
Returns:
- Type
- Date
(static) correctForOtherTimezone(date, sourceTimezone, localTimezone) → {Date}
- See:
-
- date.toLocalISO - if you want to print a date to another timezone
This helps you correct a "local date" from another timezone.
For example, if you got '2:15 PM' from a machine that is in eastern.
Combination of date.correctForTimezone and date.epochShift
For example, say you got a timezone string like this: 2024-12-27 13:30:00
You know the timezone of the source is in us/eastern
, but you are in us/central
.
If you just use Date.parse(dateString), it assumes
1:30 Central- not
1:30 Eastern`
We can correct it like this:
dateStr = '2024-12-27 13:30:00';
d = new Date(Date.parse(dateStr));
//-- the source was from 'us/eastern' timezone (-0500)
sourceTimezone = 'us/eastern';
//-- we are currently in 'us/central' timezone (-0600)
//-- this matters because of the Date.parse() done before
localTimezone = 'us/central'; // (change if yours is different)
utils.date.correctForOtherTimezone( d, sourceTimezone, localTimezone);
//-- correctly converted it to the correct local time
// 2024-12-28T18:30:00.000Z
Parameters:
Name | Type | Description |
---|---|---|
date |
Date | the date to be corrected in a new instance |
sourceTimezone |
string | the timezone of the source information |
localTimezone |
string | the timezone of this local machine |
Returns:
- new date that is corrected to UTC
- Type
- Date
(static) correctForTimezone(date, localTimezoneStr) → {Date}
- See:
-
- date.correctForOtherTimezone - if the date given is "local" but for another timezone
- date.toLocalISO - if you want to print a date to another timezone
CorrectForTimezone is the opposite of date.epochShift. (This subtracts the timezone offset to a date, where the other adds the offset)
Use this when a date string is read by javascript, BUT the timezone is not sent or passed.
For example, something VERY IMPORTANT happened at '2/1/2025, 2:15:41 PM EST', ISO '2025-02-01T20:15:41.000Z', epoch: 1738440941000.
But the dates from the database don't include the timezone.
(Note that Z
is conceptually equivalent of +0000)
If I create a date in javaScript WITHOUT the timezone, it assumes my local timezone.
dTest = new Date('2025-02-01T20:15:41.000'); // -- DID NOT INCLUDE Timezone, so it assumes local timezone
({ epoch: dTest2.getTime(), iso: dTest.toISOString(), local: dTest.toLocaleString() });
//-- time is INCORRECT, what should be the ISO time, is the local time.
// local: '2/1/2025, 8:15:41 PM', iso: '2025-02-02T02:15:41.000Z', epoch: 1738440941000
It assumed that the local time was 8pm instead of that as the ISO / GMT time.
To correct this, I just call epoch shift
dTest = new Date('2025-02-01T20:15:41.000'); // -- DID NOT INCLUDE Timezone, so it assumes local timezone
dTest2 = utils.date.epochShift(dTest, 'us/central'); //-- correct for my local timezone
({ epoch: dTest2.getTime(), iso: dTest.toISOString(), local: dTest.toLocaleString() });
//-- time is CORRECT
// local: '2/1/2025, 2:15:41 PM', iso: '2025-02-01T20:15:41.000Z', epoch: 1738440941000
See the list of TZ database time zones for the full list of timezone options.
Parameters:
Name | Type | Description |
---|---|---|
date |
Date | the date to be corrected in a new instance |
localTimezoneStr |
String | tz database name for YOUR current machine's timezone |
Returns:
- new instance of a corrected date back to UTC
- Type
- Date
(static) durationISO(epochDifference) → {String}
- See:
-
- DateRange.duration
Prints the duration in ISO format: D:HH:MM:SS.MMM
start = new Date(Date.ISO(2024, 12, 26, 12, 0, 0));
end = new Date(Date.ISO(2024, 12, 26, 13, 0, 0));
duration = end.getTime() - start.getTime();
utils.date.durationLong(duration); // '0 days, 1 hours, 0 minutes, 0.00 seconds'
Parameters:
Name | Type | Description |
---|---|---|
epochDifference |
Number | difference in milliseconds between two dates |
Returns:
D days, H hours, M minutes,S.MMMM seconds
- Type
- String
(static) durationLong(epochDifference) → {String}
- See:
-
- DateRange.duration
Prints the duration in long format: D days, H hours, M minutes, S.MMM seconds
start = new Date(Date.ISO(2024, 12, 26, 12, 0, 0));
end = new Date(Date.ISO(2024, 12, 27, 13, 0, 0));
duration = end.getTime() - start.getTime();
utils.date.durationLong(duration); // '1 days, 1 hours, 0 minutes, 0.00 seconds'
Parameters:
Name | Type | Description |
---|---|---|
epochDifference |
Number | difference in milliseconds between two dates |
Returns:
D days, H hours, M minutes,S.MMMM seconds
- Type
- String
(static) endOfDay(dateValue) → {Date}
Creates a new date that is at the end of the day (in UTC)
d = new Date('2024-12-26 6:00:00');
dEnd = utils.date.endOfDay(d); // Date('2024-12-26 23:59:59.9999')
Parameters:
Name | Type | Description |
---|---|---|
dateValue |
Date | Date where only the year,month,day is used |
Returns:
- new date set to the end of the day for dateValue's date
- Type
- Date
(static) epochShift(date, timezoneStr) → {Date}
- See:
-
- date.toEpochShiftedISO - this will print the "local time" of an epoch shifted date.
- date.toLocalISO - consider as an alternative. This prints the correct time, without updating the date object.
- date.correctForTimezone - once shifted, this allows you to shift a date back to GMT time.
EpochShift is the opposite of date.correctForTimezone. (This adds the timezone offset, where the other subtracts the offset)
Use this if you somehow have a date that needs to be shifted by the timezone offset.
For example, if you have a time that is already in GMT, and want the date shifted by a timezone.
This is used internally for date.correctForOtherTimezone if local dates are provided - but for a different timezone you yourself are not in.
Epoch shift changes the internals of a JavaScript date, so the utcDate is no longer correct, but many other functions behave closer to expected.
Once you epoch shift the date, then time stored in the date is incorrect (because it always points to GMT)
For example, using .toIsoString()
or anything with Intl.DateTimeFormat etc - will all give you incorrect results.
See here why this might not be what you want
- date.correctForTimezone or
- date.correctForTimezones.
Parameters:
Name | Type | Description |
---|---|---|
date |
Date | date to shift |
timezoneStr |
String | the tz database name of the timezone |
Returns:
- Type
- Date
(static) generateDateSequence(startDate, endDate, options) → {Array.<Date>}
- See:
-
- utils.date.add
- date.arrange - run a set of iterations instead of stopping at endDate
- DateRange.fromList - to create Date Ranges from these dates.
Creates an array of dates, beginning at startDate, and adding time until EndDate is reached.
const startDate = new Date('2025-02-02');
const endDate = new Date('2025-02-09 23:59:59.000');
// alternative
// endDate = utils.date.endOfDay(utils.date.add(startDate, { days; 7 }));
utils.date.arrange(startDate, endDate, { days: 1 });
// ['2025-02-02 00:00:00.000'],
// ['2025-02-03 00:00:00.000'],
// ['2025-02-04 00:00:00.000'],
// ['2025-02-05 00:00:00.000'],
// ['2025-02-06 00:00:00.000'],
// ['2025-02-07 00:00:00.000'],
// ['2025-02-08 00:00:00.000'],
// ['2025-02-09 00:00:00.000'],
// ['2025-02-09 23:59:59.9999']
// ]
Parameters:
Name | Type | Description | |||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
startDate |
Date | starting date |
|||||||||||||||||||||||||||||||||||
endDate |
Date | ending date |
|||||||||||||||||||||||||||||||||||
options |
Object | options similar to DateUtils.add Properties
|
Returns:
- sequence of dates from startDate to endDate
- Type
- Array.<Date>
(static) getTimezoneOffset(timezoneStr) → {TimezoneEntry}
Determines the number of milliseconds difference between a given timezone and UTC.
(Note: these values are cached, and optimized for repeated use on the same value)
See the list of TZ database time zones for the full list of options.
Parameters:
Name | Type | Description |
---|---|---|
timezoneStr |
String | a timezone string like "America/Toronto" |
Returns:
- the number of milliseconds between UTC and that timezone
- Type
- TimezoneEntry
(static) getWeekday(date, timezoneStr) → {String}
- See:
Determines the weekday of a date
Example
date = new Date('2025-01-15T06:00:00.000Z');
utils.date.getWeekday(date, 'us/pacific'); // Tue
utils.date.getWeekday(date, 'us/eastern'); // Wed
Parameters:
Name | Type | Description |
---|---|---|
date |
Date | date to print |
timezoneStr |
String | the tz database name of the timezone |
Returns:
- Currently returns
en-us
formatted day of week of a date
- Type
- String
(static) isValid(testDate) → {boolean}
Simple check on whether the a JavaScript Date object is - or is not - an 'Invalid Date' instance.
d = new Date('2024-12-1');
utils.date.isValid(d); // true
d = new Date('2024-12-1T');
utils.date.isValid(d); // false
d = new Date('some string');
utils.date.isValid(d); // false
Parameters:
Name | Type | Description |
---|---|---|
testDate |
Date | JavaScript date to validate |
Returns:
- whether the Date object is an 'invalid date' instance
- Type
- boolean
(static) localISOFormatter(timezoneStr) → {dateFormatter}
- See:
If repeatedly asking for a local time, use this method instead.
myDate = new Date('2025-01-15T06:00:00.000Z');
centralFormatter = utils.date.localISOFormatter('us/central');
centralFormatter(myDate); // '2025-01-15T00:00:00.000Z'
as opposed to
myDate = new Date('2025-01-15T06:00:00.000Z');
utils.date.toLocalISO(myDate, 'us/central'); // '2025-01-15T00:00:00.000Z'
Parameters:
Name | Type | Description |
---|---|---|
timezoneStr |
String |
Returns:
- (date) => {String} 'yyyy-mm-ddThh:mm:ss.MMM[+-]TZOFFSET'
- Type
- dateFormatter
(static) overwrite(dateToUpdate, newDateEpoch)
Overwrite the internal time for a date object.
const targetDate = new Date('2025-01-01');
utils.date.overwrite(targetDate, new Date('2025-02-01'));
targetDate.toISOString(); // 2025-02-01T00:00:00.000Z
Parameters:
Name | Type | Description |
---|---|---|
dateToUpdate |
Date | date object to modify the time in-place |
newDateEpoch |
Number | Date | the new time in epoch or Date |
Returns:
- dateToUpdate but with the internal date aligned to newDateEpoch
(static) parse(dateStr) → {Date}
- See:
-
- date.isValid - in checking for invalid dates
Harshly parses a JavaScript Date.
If the testValue is null, undefined then the same value is returned.
if the testValue is a valid Date - then the parsed Date object is returned.
If the testValue is not a valid Date, then throws an Error.
d = utils.date.parse('2024-12-01'); // returns Date object
d = utils.date.parse(0); // returns Date object
d = utils.date.parse(null); // returns null
Parameters:
Name | Type | Description |
---|---|---|
dateStr |
String | value passed to Date.parse |
Returns:
- Type
- Date
(static) startOfDay(dateValue) → {Date}
Creates a new date that is at the start of the day (in UTC)
d = new Date('2024-12-26 6:00:00');
dEnd = utils.date.startOfDay(d); // Date('2024-12-26 0:00:00.0000')
Parameters:
Name | Type | Description |
---|---|---|
dateValue |
Date | Date where only the year,month,day is used |
Returns:
- new date set to the end of the day for dateValue's date
- Type
- Date
(static) toEpochShiftedISO(date, timezoneStr) → {String}
- See:
-
- date.correctForTimezone - to shift the date back to GMT
- date.toLocalISO - if the date is not epoch shifted as this uses Intl.DateTimeFormat
Print a date that has been epoch shifted.
Dates in JavaScript are always stored in GMT, although you can format it to different times with Intl.DateTimeFormat.
Once you epoch shift the date, then time stored in the date is incorrect (because it always points to GMT)
For example, using .toIsoString()
or anything with Intl.DateTimeFormat etc - will all give you incorrect results.
If you want an ISO format for an epoch shifted date, you'll need something like this.
Parameters:
Name | Type | Description |
---|---|---|
date |
Date | Date to Print |
timezoneStr |
String | the tz database name of the timezone the date is shifted to |
Returns:
date in the format of YYYY-MM-DDTHH:mm:SS.MMMM[+-]TZ
- Type
- String
(static) toLocalISO(date, timezoneStr, includeWeekdayopt) → {String}
- See:
-
- date.localISOFormatter - if you're converting to string frequently
Prints a date in 8601 format to a timezone (with +H:MM offset) using Intl.DateTimeFormat.
The date accepted here is assumed to already have the internal clock set to GMT.
If you do epochShift, then use date.toEpochShiftedISO and pass the timezone the timezone the date is epoch shifted to.
d = Date.parse('2024-12-27 13:30:00');
utils.date.toLocalISO(d, 'america/Chicago'); // '2024-12-27T07:30:00.000-06:00'
utils.date.toLocalISO(d, 'europe/paris'); // '2024-12-27T14:30:00.000+01:00'
Sometimes it is helpful to have the weekday to make sense of things
utils.date.toLocalISO(d, 'america/Chicago', true); // '2024-12-27T07:30:00.000-06:00 FRI'
utils.date.toLocalISO(d, 'europe/paris', true); // '2024-12-27T14:30:00.000+01:00 FRI'
Parameters:
Name | Type | Attributes | Default | Description |
---|---|---|---|---|
date |
Date | date to print |
||
timezoneStr |
String | the tz database name of the timezone |
||
includeWeekday |
Boolean |
<optional> |
false
|
whether to include the weekday |
Returns:
- ISO format with timezone offset
- Type
- String
Type Definitions
TimezoneEntry
Properties:
Name | Type | Description |
---|---|---|
tz |
String | the name of the timezone |
formatter |
function | formats a date to that local timezone |
epoch |
Number | the difference in milliseconds from that tz to UTC |
offset |
String | ISO format for how many hours and minutes offset to UTC '+|-' HH:MMM |
toLocalISO |
dateFormatter | formatter function that formats a date to local ISO |
toLocalISOWeekday |
dateFormatter | formatter function that formats a date to local ISO + weekday |
getWeekday |
dateFormatter | formatter function that determines the day of week for a date |
Type:
- Object
dateFormatter(dateToFormat)
Function that is passed a date for formatting
Parameters:
Name | Type | Description |
---|---|---|
dateToFormat |
Date | the date to format |