Temporal instead of Date
Tags: javascript, programming, webdev
Published: 2022-04-02 09:35:09

JavaScript Date is fundamentally specified as the number of milliseconds that have elapsed since the [ECMAScript epoch](https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-time-values-and-time-range), which is defined as January 1, 1970, UTC. However, there are some problems with the current JavaScript `Date` implementation.

Problems 😵:
- No support for time zones other than the user's local time and UTC.
- Parser behavior so unreliable it is unusable.
- Date object is mutable.
- DST behavior is unpredictable.
- Computation APIs are unwieldy.
- No support for non-Gregorian calendars.

Actually some of the issues mentioned are fixable, we just need to add some new factory functions or make APIs to Date. Recently, there is a new API update called `Temporal` API that's going to completely revolutionize dates. Currently `Temporal` API is in Stage 3 means it's almost finalized. Do check it out and you may report bugs [here](https://github.com/tc39/proposal-temporal/issues). As it is still in experimental stage, it shouldn't be use in production.

---

The temporal API brings a new global object called `Temporal` to JavaScript that includes a lot of new methods and multiple new classes for handling a variety of date based concerns. In this article, I will cover some of the API that I personally think may often use, if you wish to know more about this API, please check out the [full docs](https://tc39.es/proposal-temporal/docs/)

## Temporal API Data Types
There are various different data types introduced in the new temporal API, but the majority of new data types are split between `plain` and `zoned` version. The only difference between these two types is `plain` represents a date/time with no timezone information. A `zoned` datetime on the other hand represents a specific date and time in a specific timezone. Besides that, there are also other data types such as `Duration`, `TimeZone` and `Calendar`.

### PlainDateTime 📆⌚
It is an object represents a date and time with no timezone information. It uses the current date and time from the timezone you pass to the method, or your current local timezone if no timezone is passed to the method.

```
const today = Temporal.Now.plainDateTimeISO()
console.log(today.toString())
// 2022-04-02T15:54:14.92305492

const date = new Temporal.PlainDateTime(2022, 1, 1)
console.log(date.toString())
// 2022-01-01T00:00:00

const date1 = Temporal.PlainDateTime.from("2022-01-01")
console.log(date1.toString())
// 2022-01-01T00:00:00
const date2 = Temporal.PlainDateTime.from({ year: 2022, month: 1, day: 1 })
console.log(date2.toString())
// 2022-01-01T00:00:00
```

### PlainDate 📆
A `PlainDate` object represents just a date with no other information.

```
const today = Temporal.Now.plainDateISO()
console.log(today.toString())
// 2022-02-21

const date1 = Temporal.PlainDate.from("2022-01-01")
console.log(date1.toString())
// 2022-01-01
const date2 = Temporal.PlainDate.from({ year: 2022, month: 1, day: 1 })
console.log(date2.toString())
// 2022-01-01
```

### PlainTime ⌚
A `PlainTime` object represents a time that has no timezone and no date.

```
const today = Temporal.Now.plainTimeISO()
console.log(today.toString())
// 16:09:22.283962281

const time1 = Temporal.PlainTime.from("04:03:25")
console.log(time1.toString())
// 04:03:25
const time2 = Temporal.PlainTime.from({ hour: 4, minute: 3, second: 25 })
console.log(time2.toString())
// 04:03:25
```

### ZonedDateTime 🗺
A `ZonedDateTime` is a datetime that contains all timezone related information.

```
const today = Temporal.Now.zonedDateTimeISO()
console.info(today.toString())
// 2022-04-02T15:54:14.306655305[America/Chicago]

const date1 = Temporal.ZonedDateTime.from("2022-01-01[America/Los_Angeles]")
console.log(date1.toString())
// 2020-01-01T00:00:00-08:00[America/Los_Angeles]

const date2 = Temporal.ZonedDateTime.from({ year: 2022, month: 1, day: 1, timeZone: "America/Los_Angeles" })
console.log(date2.toString())
// 2020-01-01T00:00:00-08:00[America/Los_Angeles]
```

### Instant ⚡
`Instant` is similar to `ZonedDateTime` but it is always in UTC time and does not take into account any particular calendar.

```
const today = Temporal.Now.instant()
console.log(today.toString())
// 2022-04-02T08:24:41.434881434Z

const date = Temporal.Instant.from("2022-01-01-06:00")
console.log(date.toString())
// 2022-01-01T06:00:00Z
```

### PlainMonthDay
Just like `PlainDate` but it does not include any year information.

```
const date1 = Temporal.PlainMonthDay.from("01-01")
console.log(date1.toString())
// 01-01
const date2 = Temporal.PlainMonthDay.from({ month: 1, day: 1 })
console.log(date2.toString())
// 01-01
```

### PlainYearMonth 
Just like `PlainDate` but it does not include any day information.

```
const date1 = Temporal.PlainYearMonth.from("2022-01")
console.log(date1.toString())
// 2022-01
const date2 = Temporal.PlainYearMonth.from({ year: 2022, month: 1 })
console.log(date2.toString())
// 2022-01
```

## Helper Methods 🛠
There are a number of helper functions we can use to solve the common use cases such as add or subtract date or date comparison.

### add ➕ / subtract ➖
As in Javascript, adding or subtracting is really annoying to do, but with temporal API all the data types have built in `add` and `subtract` methods that make it incredibly easy.

```
const today = Temporal.Now.plainDateISO()
console.log("Today: " + today.toString())
console.log("Result: " + today.add({ days: 7, months: 1 }).toString())

// Today: 2022-04-02
// Result: 2022-05-09
```

### equals 
A simple method to check whether two temporal date objects have the exact same fields.

```
const today = Temporal.Now.plainDateISO()
const today2 = Temporal.Now.plainDateISO()
console.log(today === today2)
// false
console.log(today.equals(today2))
// true
```

### with
`with` method takes in an object of fields to overwrite on the current date object.

```
const today = Temporal.Now.plainDateISO()
console.info(today.toString())
console.log(today.with({ year: 2027, month: 3 }).toString())
// 2022-04-02
// 2027-03-02
```

### compare ⚖
As method named, we can use the `compare` method to compare with temporal date object or ISO 8601 string.

```
const today = Temporal.Now.plainDateISO()
const yesterday = today.subtract({ days: 1 })
const tomorrow = '2022-04-03'
console.log([today, yesterday, tomorrow].sort(Temporal.PlainDate.compare))

// [Temporal.PlainDate <2022-04-01>, Temporal.PlainDate <2022-04-02>, '2022-04-03']
```

## Conclusion
`Temporal` API is a great API for JavaScript to deal with dates. There are currently no browsers with any support for this API yet as it is still in proposal stage 3, but you can use a polyfill if you want to try with this API. There are multiple polyfills available for this API, the one I am using is [@js-temporal/polyfill](https://www.npmjs.com/package/@js-temporal/polyfill). Thank you for your reading.