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

What is the best way to refresh a Load on Demand feature in Nativescript?

In my RadListView, the data displayed changes depending on the day selected by the user in a calendar. Currently, I am using loadOnDemandMode = "Manual" and it functions smoothly until all the available data is loaded. At that point, I trigger listView.no ...

The specified 'IArguments' type does not qualify as an array type

Currently working on crafting a personalized logger. It's a fairly straightforward process, but I'm running into some errors that are muddying up my output. Here's what I have so far: @Injectable() export class Logger { log(...args: any ...

What could be causing this TypeError to appear in my Angular unit testing?

this.columnDefs.forEach((columnDef) => { columnDef.floatingFilter = this.hasFloatingFilter; }); this.gridApi.setColumnDefs(this.columnDefs); ERROR: 'ERROR', TypeError: this.gridApi.setColumnDefs is not a function TypeError: this.gridApi.set ...

The Angular Material Table Collapse feature offers dynamic collapsing similar to jQuery Datatable

Is there a way to improve the appearance of my Angular Material Table, especially on mobile? https://i.stack.imgur.com/sZXPP.png The current display of my Angular Material Table is not aesthetically pleasing when viewed on mobile devices. https://i.stack ...

Is it possible to secure an API endpoint from unauthorized access by external authenticated users not originating from the requesting application?

Currently, I am developing an Angular application where users can log in, track their progress, and earn levels/experience points. The app uses a Node.js/Express API for backend functionality, and I need to implement a way for the app to award experience ...

Best practices and distinctions when it comes to typing in TypeScript functions

Do the typings below differ in any way, or are they essentially the same with personal preference? interface ThingA{ myFunc(): number; } interface ThingB{ myFunc: () => number; } ...

Develop a TypeScript utility function for Prisma

Having trouble inferring the correct type for my utility function: function customUtilityFunction< P, R, A extends unknown[] >( prismaArgs /* Make "where" field optional as it is already defined inside findUnique method below */, fn: ( pris ...

SmartEdit functions properly when spartacus is running using yarn start --ssl, but does not work without SSL enabled

I followed the smartedit setup instructions at and everything works well when I start the Spartacus server with yarn start --ssl. However, if I start the server with just yarn start, the storefront does not appear. See image here for reference ...

The functionality of ZoneAwarePromise has been modified within the Meteor framework

After updating to the latest Angular 2.0.1 release on Meteor 1.4.1.1, I'm facing an error that says: Zone.js has detected that ZoneAwarePromise (window|global).Promise has been overwritten I've attempted running meteor update and meteor reset, b ...

I'm looking to find the Angular version of "event.target.value" - can you help me out?

https://stackblitz.com/edit/angular-ivy-s2ujmr?file=src/app/pages/home/home.component.html I am currently working on getting the dropdown menu to function properly for filtering the flags displayed below it. My initial thought was to replicate the search ...

What could be the reason for the webpack:// not showing up in Chrome after running ng build?

Greetings, I'm relatively new to Angular and have noticed a difference between using ng serve and ng build. When I use ng serve, I can see webpack:// in the Chrome debugger which allows me to navigate my TypeScript files for debugging. However, when I ...

Can child directives in Angular 2 harness the power of parent providers?

I am facing an issue while trying to utilize a service as a provider for general use in a Directive rather than a Component. The problem arises when the service is not being received in the child Directive, despite my expectation to use it within the direc ...

Animate in Angular using transform without requiring absolute positioning after the animation is completed

Attempting to incorporate some fancy animations into my project, but running into layout issues when using position: absolute for the animation with transform. export function SlideLeft() { return trigger('slideLeft', [ state('void&a ...

Ensure that X-frame-options is set to SAMEORIGIN in Angular 6 to prevent the website from being displayed within an iframe

My goal is to prevent my site from being displayed in an <iframe> tag. After doing some research, I learned that I need to set the 'x-frame-options' header to 'SAMEORIGIN'. I attempted to accomplish this by setting the meta tag a ...

Angular 10: A Guide to Utilizing RouterModule

I'm working on enhancing one of my components by adding a button that will navigate the page to a different component : <input type="button" value="Shops List" [routerLink]="['shops-list']" class="btn&qu ...

I'm having trouble opening a new Angular project even though both my Node.js and npm are up to date. Can anyone help me

Just starting my Angular journey. I have successfully installed the latest version of node.js with npm and then added Angular CLI to it. All good until I typed this command in the node.js prompt: ng new my-app But now I'm stuck here! Any ideas on wh ...

Defined interface with specific number of members

I am tasked with creating an interface that has only two members, one of which is optional and both have undefined names. Something like: interface MyInterface { [required: string]: string|number [optional: string]?: string|number } Unfortunately, ...

Tips for parsing a string object in JSON without a preceding double quote

I'm working with an array in my Angular application, for example: searchTerm : any[] In the context of a textbox value like {'state':'tn'}, I'd like to push this to the searchTerm array. Currently, I achieve this by adding t ...

The Next.js React framework seems to be having trouble reading user input from a

I'm encountering an issue when attempting to save form email/password registration using Next.js as it is throwing an error. import {useState} from 'react' type Props = { label: string placeholder?: string onChange: () => void na ...

Exploring the world of dynamic locale with Angular 5 Pipes

My current situation involves having apps created in angular 4 and I am contemplating upgrading to angular 5. After researching how locale is managed in the pipes, it appears that upgrading may not be feasible. It seems that there are two options provided: ...