Dates in Javascript
new Date(...)
let today = new Date()
console.log('today', today) // This will automatically represent today
console.log('today - valueOf', today.valueOf()) // Returns a number MS since the UNIX epoch (midnight Jan 1 1970 UTC)
console.log('today - toString', today.toString()) // Returns the date in local timezone
Copy paste from java.util.date
- 1995 duplication
- All dates are UTC based internally
- Most methods return local time values
- Limited timezone support
Parsing Inconsistencies
// Same date, different string formats
let day1 = new Date('2023-01-09'); // 2023-01-09T00:00:00Z (UTC)
let day2 = new Date('2023-1-9'); // 2023-01-09T00:00:00 (local time) ðŸ˜
let day3 = new Date('01/09/2023'); // 2023-01-09T00:00:00 (local time) ðŸ˜
let day4 = new Date('2023-01-9'); // 2023-01-09T00:00:00 (local time) ðŸ˜
// Let's compare the dates
console.log('day1 & day2', day1.getTime() === day2.getTime())
console.log('day2 & day3', day2.getTime() === day3.getTime())
console.log('day3 & day4', day3.getTime() === day4.getTime())
// Let's look at their epoch time values
console.log('day1', day1.getTime())
console.log('day2', day2.getTime())
console.log('day3', day3.getTime())
console.log('day4', day4.getTime())
API naming conventions
// SetYear() vs setFullYear()
const setYearExample = new Date();
setYearExample.setYear(98);
console.log('setYearExample', setYearExample.toString());
setYearExample.setFullYear(98)
console.log('setYearExample', setYearExample.toString());
Server -> Client -> Server
// The server sends the time
// '2024-02-28' to represent midnight on Feb 28 2024
// and we parse it.
let serverTime = new Date('2024-02-28')
// The user does some operations of some sort and we patch the changes.
// we create the date to send it back and the server only keeps the difference
let time = `${serverTime.getYear()}-${serverTime.getMonth()}-${serverTime.getDate()}`
/*
{
clientName: 'Justin',
....
date: time
}
*/
// What is the problem here?
Server -> Client -> Server
// The server sends the time
// '2024-02-28' to represent midnight on Feb 28 2024
// and we parse it.
let serverTime = new Date('2024-02-28')
// 1. GetMonth is 0 based but getDate is not...
console.log('serverTime.getMonth()', serverTime.getMonth())
let time = `${serverTime.getYear()}-${serverTime.getMonth() + 1}-${serverTime.getDate()}`
Problem 1
Server -> Client -> Server
// The server sends the time
// '2024-02-28' to represent midnight on Feb 28 2024
// and we parse it.
let serverTime = new Date('2024-02-28')
// 1. GetMonth is 0 based but getDate is not...
// 2. GetYear is not at all what we need
console.log('serverTime.getYear()', serverTime.getYear(), 'serverTime.getFullYear()', serverTime.getFullYear())
let time = `${serverTime.getFullYear()}-${serverTime.getMonth() + 1}-${serverTime.getDate()}`
Problem 2
Server -> Client -> Server
// The server sends the time
// '2024-02-28' to represent midnight on Feb 28 2024
// and we parse it.
// 1. GetMonth is 0 based but getDate is not...
// 2. GetYear is not at all what we need...
// 3. The parsing issue strikes again...
let sad = 'ðŸ˜';
let jsDateObject = 'inconsistent, immutable, and _bad_'
Problem 3
MomentJS
2011 - 2023
Consistent Parsing
let m1 = moment('2023-03-01'); // Always parses as local time by default
let m2 = moment('2023/03/01'); // Also parses as local time
console.log('m1', m1.toString());
console.log('m2', m2.toString());
Easy Formatting
let m = moment('2025-01-01T00:00:00-05:00');
console.log('m formatted', m.tz('Asia/Tokyo').format('YYYY-MM-DD HH:mm:ss')); // "2025-01-01 14:00:00"
Date Arithmetic
let m = moment();
let nextWeek = m.add(7, 'days');
console.log('m', m.toString());
console.log('nextWeek', nextWeek.toString())
The MomentJS Cons
- Monolithic libary - 200 KB minimfied
- No modularity
- Mutability
- Slower than modern alternatives
- Deprecated
- Timezones are less robust than modern alternatives
Luxon
2015 - ????
Pros
- Immutable API
- leverages browser intl api
- modular (tree shaking)
- faster than moment
Cons
- Smaller community than moment
- Browser dependency for intl features
- migration required
Â
Temporal
2025 - ????
Reliable Parsing
let sd1 = new Date('2025-03-01'); // Interpreted as UTC in some browsers, local time in others
let sd2 = new Date('March 1, 2025'); // May fail in non-US locales
let d1 = Temporal.PlainDate.from('2025-03-01'); // Strict ISO 8601 parsing [1][4]
let d2 = Temporal.PlainDateTime.from('2025-03-01T14:30:00'); // Explicit time handling
// Error when you use a non ISO 8601 date
Temporal.PlainDate.from('2025/03/01')
https://tc39.es/proposal-temporal/docs/#string-persistence-parsing-and-formatting
Immutable
let date = Temporal.PlainDate.from('2025-03-01');
const newDate = date.add({ days: 7 }); // Returns new instance [1][6]
console.log('date', date.toString()); // '2025-03-01' (unchanged)
console.log('newDate', newDate.toString())
Time zones
// Native conflates local/UTC time unexpected
//
//
// Moment requires a plugin
//
// Conversion
let now1 = Temporal.Now.instant()
let now2 = now1.toZonedDateTimeISO('Asia/Tokyo'); // IANA Time Zone Identifiers
console.log('now1', now1.toString());
console.log('now2', now2.toString());
// direct creation
//
let now3 = Temporal.Now.zonedDateTimeISO('Europe/Paris');
console.log('now3', now3.toString());
Time Arihmetic
// Original
//
const oStart = new Date('2025-03-01');
const oEnd = new Date('2025-03-08');
const oDiff = oEnd - oStart; // Milliseconds, no direct day/month support
// Moment can use `.diff`
//
const tStart = Temporal.PlainDate.from('2025-03-01');
const tEnd = Temporal.PlainDate.from('2025-03-08');
const tDiff = tStart.until(tEnd).days; // 7
console.log('original date diff', oDiff);
console.log('Temporal date diff', tDiff)
Gregorian
// Original only supports Gregorian calendars
//
let hebrewDate = Temporal.PlainDate.from({
calendar: 'hebrew',
year: 5785,
month: 7,
day: 10
});
console.log(hebrewDate.toString()); // '2025-03-01[u-ca=hebrew]'
DST built in
// 1:30 AM on the day DST ends in Los Angeles (clocks go back from 2:00 to 1:00)
const beforeDST = Temporal.ZonedDateTime.from('2020-11-01T01:30-07:00[America/Los_Angeles]');
console.log('beforeDST', beforeDST.toString())
// Add 1 hour
const afterDST = beforeDST.add({ hours: 1 });
console.log('after', afterDST.toString());
// Output: 2020-11-01T01:30:00-08:00[America/Los_Angeles]
// Notice: The offset changes from -07:00 (PDT) to -08:00 (PST) automatically[4].
Presentation
let test = Temporal.Now.instant()
console.log('en-us', test.toLocaleString('en-US'))
console.log('fr-FR', test.toLocaleString('fr-FR'))
I'm sold
But when can I actually use Temporal
Polyfill
- https://github.com/tc39/proposal-temporal/tree/main/#polyfills

- https://caniuse.com/temporal
DateFns
xxxx - xxxx
Dates in Javascript
By themcmurder
Dates in Javascript
- 33