The timezone plugin in day.js may sometimes generate an incorrect date

For a while, I've been using dayjs in my angular project to convert timestamps from UTC to localtime. However, after my recent update, this functionality stopped working. This isn't the first issue I've encountered with dayjs, so I decided to create a utility class to handle timestamp conversion centrally. Unfortunately, this utility class fails in Angular 12, 14, and even in a typescript test project on stackblitz. Upon investigation, I found an issue with the tz function of dayjs as the isValid function returns false.

tl;dr Converting a dayjs date to another timezone in typescript results in an invalid date:

dayjs.utc(time).tz('America/New_York').isValid()

This returns false. To showcase this issue, I created a small test project on stackblitz. Here is the TimeUtil class:

import dayjs from 'dayjs';
import timezone from 'dayjs/plugin/timezone';
import utc from 'dayjs/plugin/utc';

dayjs.extend(timezone);
dayjs.extend(utc);

export class TimeUtil {
  public timeZoneLocal: string = dayjs.tz.guess();

  public debug(time: dayjs.Dayjs): Date {

    console.log('Debug Information:');
    console.log('time:', time);
    console.log('utc:', dayjs.utc(time));
    console.log('tz:', dayjs.utc(time).tz('America/New_York'));
    console.log('time valid? ', time.isValid() ? 'Yes' : 'No')
    console.log('utc valid? ', dayjs.utc(time).isValid() ? 'Yes' : 'No')
    console.log('tz valid? ', dayjs.utc(time).tz('America/New_York').isValid() ? 'Yes' : 'No')

    return dayjs.utc(time).tz('America/New_York').toDate();
  }

  public toLocal(time: dayjs.Dayjs): Date {
    return dayjs(time).tz(this.timeZoneLocal).toDate();
  }
}

The toLocal Method always returns null. To find the error, I wrote a debug method. The output of the debug method is:

Debug Information:
time: 2023-01-10T05:34:00.000Z
utc: 2023-01-10T05:34:00.000Z
tz: null
time valid? Yes
utc valid? Yes
tz valid? No

I activated esModuleInterop and allowSyntheticDefaultImports.

How can I fix my toLocal method?

Is there a simpler way to parse an utc iso datestring and convert it to a local date?

This issue seems to be related to the operating system as Firefox, Chrome, and Intellij are affected. Interestingly, everything works fine on my work PC and Android Tablet.

Answer №1

Update on ICU Library Issue

Here, I am presenting an update to address the recent problem with the International Components for Unicode (ICU) library affecting date handling in various environments.

Background Information

An ongoing chrome issue highlighted a significant change implemented by the latest version of ICU, causing discrepancies in rendering ASCII spaces within dates handled through methods like Date.prototype.toLocaleString.

This modification resulted in unexpected errors like "Invalid Date" when attempting operations such as:

new Date((new Date()).toLocaleString('en-US')) 

The impacted code also extends to libraries like dayjs, which inadvertently utilized this pattern in their timezone plugin implementation, exacerbating the issue.

const target = date.toLocaleString('en-US', { timeZone: timezone })
const diff = Math.round((date - new Date(target)) / 1000 / 60)

To rectify this issue, updates have been deployed in versions Node 19 and backported to Node 18.13 (LTS). However, users on older Node versions may encounter challenges if their ICU library is not updated accordingly.

Similar remediations are being conducted by Chrome, Mozilla, and WebKit for compatibility across their respective platforms.

Potential Solutions

  1. Amend the dayjs library using tools like yarn patch to substitute the troublesome unicode character before data re-parsing occurs.
const target = date.toLocaleString('en-US', { timeZone: timezone }).replace(/[\u202f]/, " ")
  1. Consider upgrading your browser to a version incorporating the necessary adjustments.

Original Content Below

Although unable to comment directly due to reputation constraints, I have encountered similar anomalies while working on a Node project. This issue arose recently, noticeable from Jan 20 onwards.

Environment Specifications

Setup includes an M1 MacBook Air running MacOS 12.5.1 (Monterey), utilizing dayjs version 1.10.7 without upgrades over the past 14 months and node version 16.19.0.

Observed Behavior

A parallel scenario has surfaced during testing via jest, primarily emphasizing use of dayjs() for local time retrieval, eliminating parsing hurdles.

import dayjs from "dayjs"
import timezone from "dayjs/plugin/timezone"
import utc from "dayjs/plugin/utc"

dayjs.extend(timezone)
dayjs.extend(utc)

export class TimeUtil {
  public debug(time = dayjs()) {
    console.log('Debug Information:')
    console.log('time:', time.format())
    console.log('utc:', time.utc().format())
    console.log('tz:', time.tz('America/New_York').format())
    console.log('time valid? ', time.isValid() ? 'Yes' : 'No')
    console.log('utc valid? ', time.utc().isValid() ? 'Yes' : 'No')
    console.log('tz valid? ', time.tz('America/New_York').isValid() ? 'Yes' : 'No')
  }
}

Issue emerges where the timezone object created by dayjs turns invalid.

$ yarn test tztest

Debug Information:
time: 2023-01-24T12:00:20-08:00
utc: 2023-01-24T20:00:20Z
tz: Invalid Date
time valid?  Yes
utc valid?  Yes
tz valid?  No

Temporary Docker Resolution

In contrast, conducting tests within a node:16.19.0 docker container mirrors expected behavior, hinting at environmental influences causing the discrepancy.

version: '2'
services:
  api-on-node:
    image: node:16.19.0
    container_name: api-on-node
    volumes:
      - ./:/app
    working_dir: /app
    tty: true
    environment:
      - TZ=America/Los_Angeles
$ docker exec -it api-on-node yarn test tztest

Debug Information:
time: 2023-01-24T12:00:21-08:00
utc: 2023-01-24T20:00:21Z
tz: 2023-01-24T15:00:21-05:00
time valid?  Yes
utc valid?  Yes
tz valid?  Yes

Further investigation into root cause variations leading up to this disparity remains ongoing, acknowledging these shifts demand thorough attention.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Transforming various date formats into the en-US format of mm/dd/yyyy hh:mm:ss can be accomplished through JavaScript

When encountering a date format in en-GB or European style (mm.dd.yyyy), it should be converted to the en-US format (mm/dd/yyyy). If the date is not already in en-US format, then it needs to be converted accordingly. ...

The template literal expression is invalid due to the "string | null" type when sending authorization

While working on implementing authorization, I encountered an error from Ts-eslint stating that there was an "Invalid type 'string | null' of template literal expression" when trying to execute the functionality. The data being retrieved from lo ...

Understanding how to efficiently map through FontAwesome icons using React TypeScript and effectively showcase them on the frontend

I am in the process of developing a versatile component that allows me to input the href, target, and rel attributes, along with specifying the FontAwesome Icon I want to utilize. My goal is to be able to pass multiple icons into this list, which will then ...

Could someone clarify for me why I am unable to view the connection status within this code?

Having trouble with the Ionic Network plugin. I've included this code snippet, but it's not functioning as expected. No console logs or error messages are showing up. import { Network } from '@ionic-native/network'; ionViewDidLoad() { ...

I keep seeing "Uncaught TypeError: Unable to retrieve property 'get' from undefined" error message popping up

Currently, I am attempting to retrieve a JSON from a separate microservice (local) utilizing a different port. There is uncertainty as to whether the issue lies within my configuration or the microservice itself. Despite successfully displaying the JSON on ...

Making Angular table cells interactive with clicks

My table consists of multiple rows, and I want to change the color of a cell to red when clicked. However, only one cell should be red at a time. Whenever I click on a new cell, the previously red cell should return to its original color. How can I achieve ...

Transforming AngularJS 2.0 code into ES6 syntax

Successfully implemented the AngularJS 2.0 5 Minute Quickstart in my IntelliJ IDEA 14.1.4 following a helpful Stackoverflow Answer on AngularJS 2.0 TypeScript Intellij idea (or webstorm) - ES6 import syntax. However, it seems to focus on compiling TypeScr ...

Retrieve the values of a dynamic JSON object and convert them into a comma-separated string using Typescript

I recently encountered a dynamic JSON object: { "SMSPhone": [ "SMS Phone Number is not valid" ], "VoicePhone": [ "Voice Phone Number is not valid" ] } My goal is to extract the va ...

Troubleshooting form submission issues in Angular 4

I am encountering a few issues with my search form. It is supposed to function as a search tool with one input field and one button. However, something seems amiss. I am utilizing an API that returns values based on the string inputted. When an empty value ...

Maximizing the potential of process.hrtime.bigint

Whenever I include the following code: const a = process.hrtime.bigint(); The linter says it's okay, but during compilation, I encounter this error message: error TS2339: Property 'bigint' does not exist on type 'HRTime'. This ...

Unforeseen results arise when using the ng-if directive on a DIV element within an Angular context

@angular/upgrade/static Attempting to upgrade an AngularJS controller to Angular context using UpgradeModule from '@angular/upgrade/static' Encountering issues when changing ng-show to ng-if on span or div elements, as the enclosed content does ...

Turn off basic authentication for serving static content with Spring Security

I am facing an issue with my setup where I have an Angular app served as static content from a Spring Boot app. The Angular app is located inside target/classes/static/index.html of the Spring Boot application. Additionally, I have a REST API served from t ...

Inquiry about how TypeScript handles object property references when passed into functions

As a newcomer to TypeScript, I am exploring the creation of a range slider with dual handles using D3.js. I have developed a simple class for managing the slider objects: export class VerticalRangeSlider{ private sliderContainer: d3.Selection<SVGG ...

Retrieving a data type from the key values of deeply nested objects

I'm currently working with JSON data that contains nested objects, and my goal is to extract the unique set of second-level keys as a type. For instance: const json = { 'alice': { 'dogs': 1, 'birds': 4 ...

Guidelines on incorporating emotion/styled into React applications with TypeScript

Including my root component in the ThemeProvider from @emotion/react has granted me access to props.theme. Here is an example: const StyledDiv = styled.div` background-color: ${(props) => props.theme.palette.primary.main}; `; Issue: TypeScript indica ...

Modify certain parameters in the current route using Angular 6 router

Within my Angular 6 setup, the URLs are structured as follows: /{language}/{app_section}/{object_id}/{view}?queryparams... All sections of the application utilize a language selector component, which is included in the template of a parent route to ensur ...

Creating an object instance in Angular 2 using TypeScript

Looking for guidance on creating a new instance in TypeScript. I seem to have everything set up correctly, but encountering an issue. export class User implements IUser { public id: number; public username: string; public firstname: string; ...

HTTP Interceptor never finishes executing (finalization is never triggered)

In my angular 8 project, I created a basic HttpInterceptor that simply duplicates the original request and includes an additional parameter: @Injectable() export class RequestHeadersInterceptor implements HttpInterceptor { intercept(request: HttpReques ...

Customize the style of Angular Material within an Angular component

In my Angular component, I am utilizing Material 2's <md-input-container>. I am looking to customize a specific class, such as .mat-input-wrapper, that is originally defined in Angular Material. However, my intention is for this customization to ...

Create a Jest mock for a namespace and a function that have the same name

The structure of a library I'm currently using is as follows: declare namespace foo { function bar(); }; declare namespace foo.bar { function baz(); }; My task involves mocking the functions foo.bar() and foo.bar.baz(). To mock foo.bar(), ...