Luxon Timezones and JS-Date interop
Tags: javascript, webdev, typescript
Published: 2022-11-23 16:00:20

If you ever wondered how [luxon](https://moment.github.io/luxon/) and native [JS-Dates](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date?retiredLocale=de) (with TimeZones) behave when converting them between each other and [ISO-Date-Strings](https://www.w3.org/TR/NOTE-datetime) here are my tests:

```ts
import {DateTime} from 'luxon'

const date = new Date();
const offset = date.getTimezoneOffset();
console.log('TimeZoneOffset(min): ', offset * -1);
console.log('TimeZoneOffset( h ): ', offset / 60 * -1);

/*
TimeZoneOffset(min):  60
TimeZoneOffset( h ):  1
 */

const strLocal = '2023-07-21T09:35:31.825+01:00'
const strUtc = '2023-07-21T08:35:31.825Z'

const jsDateLocal = new Date(strLocal)
const jsDateUTC = new Date(strUtc)

const dateTimeLocal = DateTime.fromISO(strLocal)
const dateTimeUTC = DateTime.fromISO(strUtc)

console.log(`ToLocal`)
console.table({
  jsDateLocal: jsDateLocal.toLocaleString(),
  jsDateUTC: jsDateUTC.toLocaleString(),
  dateTimeLocal: dateTimeLocal.toLocaleString(),
  dateTimeUTC: dateTimeUTC.toLocaleString(),
  dateTimeLocalFull: dateTimeLocal.toLocaleString(DateTime.DATETIME_FULL),
  dateTimeUTCFull: dateTimeUTC.toLocaleString(DateTime.DATETIME_FULL),
})

/*
┌───────────────────┬───────────────────────────────────┐
│      (index)      │              Values               │
├───────────────────┼───────────────────────────────────┤
│    jsDateLocal    │     '7/21/2023, 10:35:31 AM'      │
│     jsDateUTC     │     '7/21/2023, 10:35:31 AM'      │
│   dateTimeLocal   │            '7/21/2023'            │
│    dateTimeUTC    │            '7/21/2023'            │
│ dateTimeLocalFull │ 'July 21, 2023 at 10:35 AM GMT+2' │
│  dateTimeUTCFull  │ 'July 21, 2023 at 10:35 AM GMT+2' │
└───────────────────┴───────────────────────────────────┘
 */

console.log(`ToIsoTimestamp`)
console.table({
  jsDateLocalToIso: jsDateLocal.toISOString(),
  jsDateUTCToIso: jsDateUTC.toISOString(),

  dateTimeLocalToIso: dateTimeLocal.toISO(),
  dateTimeUtcToIso: dateTimeUTC.toISO(),

  dateTimeLocalToUtcToIso: dateTimeLocal.toUTC().toISO(),
  dateTimeUtcToUtcToIso: dateTimeUTC.toUTC().toISO(),
})
/*
┌─────────────────────────┬─────────────────────────────────┐
│         (index)         │             Values              │
├─────────────────────────┼─────────────────────────────────┤
│    jsDateLocalToIso     │   '2023-07-21T08:35:31.825Z'    │
│     jsDateUTCToIso      │   '2023-07-21T08:35:31.825Z'    │
│   dateTimeLocalToIso    │ '2023-07-21T10:35:31.825+02:00' │
│    dateTimeUtcToIso     │ '2023-07-21T10:35:31.825+02:00' │
│ dateTimeLocalToUtcToIso │   '2023-07-21T08:35:31.825Z'    │
│  dateTimeUtcToUtcToIso  │   '2023-07-21T08:35:31.825Z'    │
└─────────────────────────┴─────────────────────────────────┘
 */


console.log(`jsDate to DateTime to Iso`)
console.table({
  fromJsLocal: DateTime.fromJSDate(jsDateLocal, ).toISO(),
  fromJsUTC: DateTime.fromJSDate(jsDateUTC).toISO(),

  fromJsLocalWithUtc: DateTime.fromJSDate(jsDateLocal, {zone: 'utc'}).toISO(),
  fromJsUTCWithUtc: DateTime.fromJSDate(jsDateUTC, {zone: 'utc'}).toISO(),

  fromJsLocalToUtc: DateTime.fromJSDate(jsDateLocal).toUTC().toISO(),
  fromJsUTCToUtc: DateTime.fromJSDate(jsDateUTC).toUTC().toISO(),

  fromJsLocalWithEuropeBerlin: DateTime.fromJSDate(jsDateLocal, {zone: 'Europe/Berlin'}).toISO(),
  fromJsUTCWithEuropeBerlin: DateTime.fromJSDate(jsDateUTC, {zone: 'Europe/Berlin'}).toISO(),

  fromJsLocalWithEuropeBerlinToUtc: DateTime.fromJSDate(jsDateLocal, {zone: 'Europe/Berlin'}).toUTC().toISO(),
  fromJsUTCWithEuropeBerlinToUtc: DateTime.fromJSDate(jsDateUTC, {zone: 'Europe/Berlin'}).toUTC().toISO(),
})

/*
┌──────────────────────────────────┬─────────────────────────────────┐
│             (index)              │             Values              │
├──────────────────────────────────┼─────────────────────────────────┤
│           fromJsLocal            │ '2023-07-21T10:35:31.825+02:00' │
│            fromJsUTC             │ '2023-07-21T10:35:31.825+02:00' │
│        fromJsLocalWithUtc        │   '2023-07-21T08:35:31.825Z'    │
│         fromJsUTCWithUtc         │   '2023-07-21T08:35:31.825Z'    │
│         fromJsLocalToUtc         │   '2023-07-21T08:35:31.825Z'    │
│          fromJsUTCToUtc          │   '2023-07-21T08:35:31.825Z'    │
│   fromJsLocalWithEuropeBerlin    │ '2023-07-21T10:35:31.825+02:00' │
│    fromJsUTCWithEuropeBerlin     │ '2023-07-21T10:35:31.825+02:00' │
│ fromJsLocalWithEuropeBerlinToUtc │   '2023-07-21T08:35:31.825Z'    │
│  fromJsUTCWithEuropeBerlinToUtc  │   '2023-07-21T08:35:31.825Z'    │
└──────────────────────────────────┴─────────────────────────────────┘
 */
```